Python基础之文件操作

一:文件打开操作

def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True): # known special case of open

打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常

f = open('test.txt')	# file对象
# windows <_io.TextIOWrapper name='test' mode='r' encoding='cp936'
# linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'
print(f.read())			# 读取文件(不加参数会将文件中所有内容读取到内存中)
f.close()				# 关闭文件

文件操作中,最常用的操作就是读和写。文件访问的模式有两种:文本模式和二进制模式。不同模式下,操作函数也不尽相同,表现的结果也不一样。

open的参数
file:打开或者要创建的文件名。如不指定路径,默认就是当前路径。
mode模式:

描述字符意义
r缺省的,表示只读打开。使用write方法抛异常;文件不存在抛异常
w只写打开。如果读取则抛异常;文件不存在则创建文件;文件存在则清空文件内容再写入新内容
x创建并写入一个新文件。文件不存在则创建文件,并只写方式打开;文件存在则抛异常
a写入打开。如果文件存在,则追加;文件不存在则创建后只写方式打开追加内容
b二进制模式。字节流,将文件按照字节理解,与字符编码无关。二进制模式操作时,字节操作使用bytes类型
t缺省的,文本模式。字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode就是rt
+读写打开一个文件。给原来只读,只写方式打开提供缺失的读或者写能力

文件指针(默认指定当前字节位置):
mode=r:指针起始在0
mode=a:指针起始在EOF
tell():显示指针当前位置
seek(offset[,whence]):移动文件指针位置。offset偏移多少字节,whence从哪里开始。

文本模式下:
whence 0缺省值,表示从头开始,offset只能正整数
whence 1表示从当前位置,offset只接受0
whence 2表示从EOF开始,offset只接受0

二:上下文管理

lst = []
for _ in range(2000):
    lst.append(open('test.txt'))
print(len(lst))
# 如果linux系统没有做过优化,会抛下面的异常
# OSError: [Error 24] Too many open files: test.txt

ulimit -a查看系统所有的限制。其中open files就是打开文件数的限制,默认为1024。由于上面的代码没有将打开的文件关闭,避免系统资源浪费,将打开的文件全部关闭

for x in lst:
    x.close()

如何处理异常?当出现异常的时间,拦截异常。但是,因为很多代码都可能出现OSError异常,还不好判断异常就是因为资源限制产生的。

f = open('test.txt')
try:
    f.write('abc')
finally:			# 使用finally可以保证打开的文件可以被关闭
    f.close()

上下文管理:一种特殊的语法,交给解释器去释放文件对象。

with open('test.txt') as f:
    result = f.read()		# 默认以只读模式打开文件
    print(result)
    # raise ValueError()
print(f.closed)				# True 测试f是否已关闭,True为关闭

上下文管理:

  1. 使用with…as关键字
  2. 上下文管理的语句块并不会开启新的作用域
  3. with语句块执行完的时候,会自动关闭文件对象

实例1:指定一个源文件,实现copy到目标目录。如把当前目录下的/tmp/test.txt拷贝为test.txt.copy

origin_file = 'test.txt'
dest_file = 'test.txt.copy'
with open(origin_file) as f1:
    with open(dest_file, 'w') as f2:
        content = f1.read()
        f2.write(content)
# 注:不会拷贝文件的元信息,只会拷贝文件内容        

实例2:有一个文件,对其进行单词统计,不区分大小写,并显示单词重复最多的10个单词

def word_count(file = 'test.txt'):
    chars = '''~!@#$%^&*()_+{}[]|\\/=;:.'<>?'''
    with open(file, encoding='utf-8') as f:
        count = {}
        for line in f:
            words = line.split()
            # print(words)
            for k, v in zip(words, (1,)*len(words)):
                k = k.strip(chars)
                k = k.lower()
                count[k] = count.get(k,0) + 1
    lst = sorted(count.items(), key = lambda x: x[1], reverse=True)
    # for i in range(10):
    #     print(str(lst[1]).strip("'()").replace("'", ""))
    return lst
wc = word_count()
print(wc)
print(len(wc))

三:StringIO与BytesIO

3.1 StringIO

io模块中的类:

from io import StringIO

内存中,开辟一个文本模式的buffer,可以像文件对象一样操作它。当close方法被调用的时候,这个buffer会被释放

from io import StringIO
# 内存中构建
s = StringIO()      	# 像文件对象一样操作
print(s.readable(), s.writable(), s.seekable())	# 可读,可写,可seek
s.write("Life is short,\nyou need Python")		# 这里要用双引号,单引号换行符不起作用
s.seek(0)				# 移动指针到开头
print(s.readline())
print(s.getvalue())     # 无视指针,输出全部内容
s.close()

好处:一般来说,磁盘的操作比内存的操作要慢得多,内存足够的情况下,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程序的运行效率。

3.2 BytesIO

io模块中的类:

from io import BytesIO

内存中,开辟一个二进制模式的buffer,可以像文件对象一样操作它。当close方法被调用时,这个buffer会被释放。

from io import BytesIO
s = BytesIO()      	# 像文件对象一样操作
print(s.readable(), s.writable(), s.seekable())	# 可读,可写,可seek
s.write(b'Life is short,\nyou need Python')
s.seek(0)				# 移动指针到开头
print(s.readline().decode())
print(s.getvalue().decode())     # 无视指针,输出全部内容
s.close()

3.3 file-like对象

类文件对象,可以像文件对象一样操作。socket对象、输入输出对象(stdin, stdout)都是类文件对象

from sys import stdout
f = stdout
print(type(f))
f.write('Life is short, you need python')
# <class '_io.TextIOWrapper'>
# Life is short, you need python

四:文件修改操作

文件的修改操作要为以下五个步骤:

  1. 以读的模式打开原文件
  2. 以写的模式打开一个新文件
  3. 将原文件的内容读取到内存按照要求进行修改,形成新内容写入新文件
  4. 将原文件删除
  5. 将新文件生命成原文件
import os
with open('test.txt', encoding='utf-8') as f1:
    with open('test_new.txt', 'w', encoding='utf-8') as f2:
        for line in f1:
            new_content = line.replace('you', 'your')
            f2.write(new_content)
os.remove('test.txt')
os.renames('test_new.txt', 'test.txt')

五:shutil模块

上面所说的文件拷贝使用打开两个文件对象,源文件读取内容,写入目标文件中来完成拷贝过程。但是这样丢失了stat数据信息(权限等)。python提供了一个方便的库:shutil(高级文件操作)

5.1 copy

copyfileobj(fsrc,fdst[,length])

文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容。fdst要求可写。length指定了buffer的大小。

copyfile(src, dst, *, follow_symlinks=True)		# 不包含元数据,本质上调用的就是copyfileobj
copymode(src, dst, *, follow_symlinks=True)		# 仅仅复制权限
copystat(src, dst, *, follow_symlinks=True)		# 复制元数据,包含权限
copy(src, dst, *, follow_symlinks=True)			# 拷贝文件内容,权限,部分元数据,不包括创建时间和修改时间,本质上调用copyfile与copymode
copy2(src, dst, *, follow_symlinks=True)		# 比copy多个复制全部元数据,需要平台支持。本质上调用copyfile, copystate
copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False)
# 递归复制目录。默认使用copy2,也就是带更多的元数据复制
rmtree(path, ignore_errors=False, onerror=None)	# 递归删除。慎用。它不是原子操作,有可能删除错误就会中断,已经删除的就删除了。
move(src, dst, copy_function=copy2)				# 递归移动文件,目录到目标,返回目标。

shutil还有打包功能。生成tar并压缩。支持zip, gz, bz, xz。

六:json文件处理

json本质上就是一个字符串

6.1 字典和列表转json

import json
person = [
    {
        "username": "Bruce",
        'age': 30
    },
    {
        "username": '天龙八部',
        "age": 32
    },
]
json_str = json.dumps(person, ensure_ascii=False)
print(json_str, type(json_str))
# 没有ensure_ascii=False参数的输出
# [{"username": "Bruce", "age": 30}, {"username": "\u5929\u9f99\u516b\u90e8", "age": 32}] <class 'str'>
# 有ensure_ascii=False参数的输出
# [{"username": "Bruce", "age": 30}, {"username": "天龙八部", "age": 32}] <class 'str'>

因为json在dump时,只能存放ascii的字符,因此会将中文进行转义,此时可以使用ensure_ascii=False关闭这个特性。
在Python中只有基本数据类型才能转换成JSONS格式的字符串。即:int, floot, str, list, dict, tuple。

6.2 json数据dump到文件

json模块中除了dumps函数,还有一个dump函数,这个函数可以传入一个文件指针,直接将字符串dump到文件中。

import json
person = [
    {
        "username": "Bruce",
        'age': 30
    },
    {
        "username": '天龙八部',
        "age": 32
    },
]
with open('a.json', 'w', encoding = 'utf-8') as f:
    json.dump(person, f, ensure_ascii=False)

6.3 将json字符串load成python对象

json_str = '[{"username": "Bruce", "age": 30}, {"username": "天龙八部", "age": 32}]'
ret = json.loads(json_str, encoding='utf-8')
print(ret, type(ret))

直接从文件中load:

with open('a.json', 'r', encoding='utf-8') as f:
    person = json.load(f)
    print(person, type(person))

七:csv数据

写入csv数据:

import csv
header = ['id', 'title', 'lecture', 'price']
rows = [(1,'Python','Andy',200),(2,'Java','Jackie',100),(3,'PHP','Mike','288')]
with open('data1.csv', 'w', encoding = 'utf8') as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(rows)

读CSV数据:

import csv
with open('data1.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
# 每一行数据都是一个列表  
import csv
with open('data1.csv') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)    # OrderedDict([('id', '1'), ('name', 'Tom'), ('score', '80')])
        for k,v in row.items():
            print(k,v)

八:excel文件处理

官方文档:

https://openpyxl.readthedocs.io/en/stable/

8.1 安装

pip install openpyxl
pip install Pillow
# 想要在文件中插入图片文件,需要安装pillow

8.2 简单使用

from openpyxl import Workbook
import datetime
import time
wb = Workbook()    #创建文件对象
# grab the active worksheet
ws = wb.active     #获取第一个sheet
# Data can be assigned directly to cells
ws['A1'] = 42      #写入数字
ws['B1'] = "你好"+"automation test" #写入中文(unicode中文也可)
# Rows can also be appended
ws.append([1, 2, 3])    #写入多个单元格
ws['A3'] = datetime.datetime.now()    #写入一个当前时间
ws['A4'] =time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())  #写入一个自定义的时间格式
wb.save("e:\\sample.xlsx")

写入表格后的数据:
Python基础之文件操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值