python文件操作处理 (六)

文件操作

冯诺依曼体系架构

在这里插入图片描述

  • CPU由运算器和控制器组成
  • 运算器,完成各种算数运算、逻辑运算、数据传输等数据加工处理
  • 控制器,控制计算机各部件协调运行
  • 存储器,用于记忆程序和数据,例如内存
  • 输入设备,将数据或者程序输入到计算机中,例如键盘、鼠标
  • 输出设备,将数据或程序的处理结果展示给用户,例如显示器、打印机等
    一般说IO操作,指的是文件IO,如果指的是网络IO,都会直接说网络IO

文件IO常用操作

在这里插入图片描述

打开操作

open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd= True, opener=None)

  • 打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常
  • 基本使用:
    创建一个文件test,然后打开它,用完关闭
f = open("tese") # file对象
# windows <_io.TextIOWrapper name='tese' mode='r' encoding='cp936'>
# linux <_io.TextIOWrapper name='tese' mode='r' encoding='UTF-8'>
print(f.read()) # 读取文件
f.close() # 关闭文件
12345
  • 文件操作中,最常用的操作就是 “读”“写”
  • 文件访问的模式有两种:
  • 文本模式和二进制模式。不同模式下,操作函数不相同,表现的结果也不一样
    注:
  • windows中使用codepage代码页,可以认为每一个代码页就是一张编码表。cp936等同于GBK

open的参数

  • file
  • 打开或者要创建的文件名。如果不指定路径,默认是当前路径
  • mode模式
    在这里插入图片描述
    在上面的例子中,可以看到默认是文本打开模式,且是只读的

r 模式

  • 只读打开文件,如果使用write方法,会抛异常
  • 如果文件不存在,抛出FileNotFoundError异常
  • open模式是只读模式r打开已存在的文件
    在这里插入图片描述

w 模式

  • 表示只写打开方式,如果读取则抛出异常
  • 如果文件不存在,则直接创建文件
  • 如果文件存在,则清空文件内容
    在这里插入图片描述

x 模式

  • 文件不存在,创建文件,并只写方式打开
  • 文件存在,抛出FileExistsError异常
    在这里插入图片描述

a 模式

  • 文件存在,只写打开,追加内容
  • 文件不存在,则创建后,只写打开,追加内容
    在这里插入图片描述

总结

  • r 是只读,wxa 都是只写
  • wxa 模式都可以产生新文件
    w 不管文件存在与否,都会生成全新内容的文件
    a 不管文件是否存在,都能在打开的文件尾部追加
    x 必须要求文件事先不存在,自己创建一个新文件

文本模式 t

  • 字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode就是 rt

二进制模式 b

  • 字节流,将文件就按照字节理解,与字符编码无关。二进制模式操作时,字节操作使用bytes类型
f = open("test3",'rb') # 二进制只读
s = f.read()
print(type(s)) # bytes
print(s)
f.close() # 关闭文件

f = open("tese3",'wb') # IO对象
s = f.write("你好".encode()) # encode默认使用UTF-8编码,一个中文3个字节
print(s) #   6
f.ckose()
12345678910

+ 模式

  • 为r、w、a、x提供缺失的读或写功能,但是获取文件对象依旧按照r、w、a、x自己的特征
  • +模式不能单独使用,可以认为它是为前面的模式字符做增强功能的

文件指针

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

文本模式下

whence 0 缺省值,表示从头开始,offest只能正整数
whence 1 表示从当前位置,offest只接受0
whence 2 表示从EOF开始,offest只接受0
在这里插入图片描述

  • 文本模式支持从开头向后偏移的方式
  • whence为1表示从当前位置开始偏移,但是只支持偏移0,相当于原地不动,所以没什么用
  • whence为2表示从EOF开始,只支持偏移0,相当于移动文件指针到EOF
  • seek是按照字节偏移的
  • read在文本模式是按照字符读取的

二进制模式下

whence 0 缺省值,表示从头开始,offest只能正整数
whence 1 表示从当前位置,offest可正可负
whence 2 表示从EOF开始,offest可正可负
在这里插入图片描述
二进制模式支持任意起点的便宜,从头、从尾、从中间位置开始
向后seek可以超界,但是向前seek的时候,不能超界,否则抛异常

buffering:缓冲区

  • -1表示使用缺省大小的buffer。如果是二进制模式,使用价格io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192。如果是文本模式,如果是终端设备,实行缓存方式,如果不是,则使用二进制模式的策略
  • 0,只在二进制模式使用,表示关buffer
  • 1,只在文本模式使用,表示使用行缓冲。意思就是见到换行符就flush
  • 大于1,用于指定buffer的大小

buffer缓冲区

  • 缓冲区一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或者达到阈值,数据才会flush到磁盘。
fluch()
  • 将缓冲区数据写入磁盘
chlose()
  • 关闭前会调用flush()
  • io.DEFAULT_BUFFER_SIZE 缺省缓冲区大小,字节
二进制模式
import io

f = open('test','w+b')
print(io.DEFAULT_BUFFER_SIZE) # 8192
f.write("hello".encode())
# cat test
f.seek(0) # 指针回0
# cat test
f.write('python'.encode())
f.flush()
f.close()


f = open('test','w+b',4) # 缓冲区大小
f.write(b'hello')
# cat test
f.write(b'python')
# cat test
f.close()
12345678910111213141516171819
文本模式
import io

# buffering=1,使用行缓冲
f = open('test','w+',1)
f.write('hello') # cat test
f.write('python'*4) # cat test
f.write('\n') # cat test
f.write('hi\nPython') # cat test
f.close()

#buffering>1,使用指定大小的缓冲区
f = open('test','w+',15)
f.write('hello') # cat test
f.write('python') # cat test
f.write('hi\n') # cat test
f.write('\nPython') # cat test
f.write('a' * (io.DEFAULT_BUFFER_SIZE - 20)) # 设置为大于1没什么用
f.write('\nhelloPython')
f.close()
12345678910111213141516171819
  • buffering=0
  • 这是一种特殊的二进制模式,不需要内存的buffer,可以看作是一个FIFO的文件
f = open('test','wb+',0)
f.write('hello') # cat test
f.write('python'*4) # cat test
f.write('\n') # cat test
f.write('hi\nPython') # cat test
f.close()
123456

在这里插入图片描述

  1. 文本模式,一般都用默认缓冲区大小
  2. 二进制模式,是一个个字节的操作,可以指定buffer的大小
  3. 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它
  4. 一般编程中,明确知道需要写磁盘了,都会手动调用一次flush,而不是等到自动flush或者close的时候

encoding:编码,仅文本模式使用

  • None表示使用缺省编码,依赖操作系统。windows、linux下测试如下代码
f = open('test','w')
f.write('啊')
f.close()
123

windows下缺省GBK(0xB0A1),linux下缺省UTF-8(0xE5 95 8A)

其他参数

errors

  • 什么样的编码错误将被捕获
  • None和strict表示有编码错误将抛出ValueError异常;ignore表示忽略

newline

  • 文本模式中,换行的转换。可以用None、“空串、’\r’、’\n’、’\r\n’
  • 读时,None表示’\r’、’\n’、’\r\n’都被转换为’\n’;’'空串表示不会自动转换通用换行符;其它合法字符表示换行符就是指定字符,就会按照指定字符分行
  • 写时,None表示’\n’都会被替换为系统缺省行分割符os.linesep;’\n’或’‘空串表示’\n’不替换;其它合法字符表示’\n’会被替换为指定的字符
f = open('/etc/test', 'w')
# newline缺省为None,windows下会把\n替换为\r\n
f.write('python\rwww.python.org\nwww.baidu.com\r\npython3')
# 真正写入的是
# 'python\rwww.python.org\rwww.baidu.com\r\rpython3'
f.close()

newlines = [None, '', '\n', '\r\n']
for nl in newlines:
    f = open('/etc/test', newline=nl) # 缺省替换所有换行符
    print(f.readlines())
    f.close()
# 运行结果如下
# ['python\n', 'www.python.org\n', 'www.baidu.con\n', '\n', 'python3']
# 常见换行符都替换为\n
# ['python\r', 'www.python.org\r\n', 'www.baidu.con\r', '\r\n', 'python3']
# ''表示什么都不做
# ['python\rwww.python.org\r\n', 'www.baidu.con\r\r\n', 'python3']
#  \n做作为换行符
# ['python\rwww.python.org\r\n', 'www.baidu.con\r\r\n', 'python3']
# \r\n作为换行符
123456789101112131415161718192021

closefd

  • 表示文件描述符,True表示关闭它。False会在文件关闭后保持这个描述符。fileobj.fileno()查看

read

  • read(size=-1)
  • size表示读取的多少个字符或字节;负数或者None表示读取到EOF
f = open('/etc/test', 'r+')
f.write("hello")
f.write('\n')
f.write('你好')
f.seek(0)
f.read(7)
f.close()
# 二进制
f = open('/etc/test', 'rb+')
f.read(7)
f.read(1)
f.close()
123456789101112

行读取

readline(size=1)

  • 一行行读取文件内容。size设置一次能读取行内几个字符或字节

readlines(hint=-1)

  • 读取所有行的列表。指定hint则返回指定的行数
# 按行迭代
f = open('test') # 返回可迭代对象

for line in f:
	print(line.encode())

f.close()
1234567

write

  • write(s),把字符串s写入到文件中并返回字符的个数
  • writelines(lines),将字符串列表写入文件
f = open('test', 'w+')

line = ['abc', '123\n', 'hello'] # 提供换行符
f.writelines(lines)

f.seek(0)
print(f.read())
f.close()
12345678

close

  • flush并关闭文件对象
  • 文件已经关闭,再次关闭没有任何效果

其他

在这里插入图片描述

上下文管理

  • 在Linux中,执行
lst = []
for _ in range(2000):
	lst.append(open('test'))
# OSError: [Errno 24] Too many open files: 'test'

print(len(lst))
123456

lsof:列出打开的文件

没有就# yum install lsof

$ ps aux | grep python
$ lsof -p 9255 | grep test |wc -1
$ ulimit -a
123
  • ps命令返回进程,grep处python进程ID
  • lsof -p 进程号,列出该进程的所有文件描述符,grep出test文件的文件描述符,wc统计
  • ulimit -a 查看所有限制。其中open files就是打开问价数的限制,默认1024
for x in lst:
	x.close()
12

将文件一次关闭,然后就可以继续打开了。再看一次lsof
1、异常处理

  • 当出现异常的时候,拦截异常。但是,因为很多代码都可能出现OSError异常,还不好判断异常就是因为资源限制产生的
f = open('test')
try:
	f.writs("abc") # 文件只读,写入失败
finally:
	f.close() # 这样才行
12345
  • 使用finally可以保证打开的文件可以被关闭
    2、上下文管理
    一种的特殊语法,交给解释器去释放文件对象

上下文管理

del f
with open('test') as f:
	f.write('abc') # 文件只读,写入失败

#测试f是否关闭
f1.closed
123456
  • 对于类似文件对象的IO对象,一般来说都需要在不使用的时候关闭、注销,以释放资源
  • IO被打开的时候,会获得一个文件描述符。计算机资源是有限的,所以操作系统都会做限制。就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,不是独占的
  • 一般情况下,除非特别明确的知道资源情况,否则不要提高资源的限制值来解决问题

StringIO

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

getvalue()

  • 获取全部内容。跟文件指针没有关系
from io impoer StringIO

# 内存中构建
sio = StringIO() # 像文件对象一样操作
print(sio.readable(), sio.writable(), sio.seekable())
sio.write("hello\nPython)
sio.seek(0)
print(sio.readline())
print(sio.getvalue()) # 无视指针,输出全部内容
sio.close()
12345678910

好处

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

BytesIO

  • io模块中的类
    from io impoet BytesIO
  • 内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它
  • 当close方法被调用的时候,这个buffer会被释放
from io import BytesIO # 内存中构建
bio = BytesIO()
print(bio.readable(), bio.writable(), bio.seekable())
bio.write(b'hello\nPython')
bio.seek(0)
print(bio.readline())
print(bio.getvalue()) # 无视指针,输出全部内容
bio.close()
12345678

file-like对象

  • 类文件对象、可以像文件对象一样操作
  • socket对象、输入输出对象(stdin、stdout)都是类文件对象
from sys import stdout, stderr
f = stdout
print(type(f))
f.write('hello')
f.close()

路径操作模块

3.4版本之前

os.path模块

from os import path
p = path.join('/etc', 'sysconfig', 'network') # 拼接
pring(type(p), p)
print(path.exists(p)) # 存在

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值