第五章:文件和I/O

任何程序都需要处理输入和输出。本章节介绍了处理各种不同类型文件时的惯用方法,包括文本和二进制人间的处理,文件的编码以及其他的一些相关内容。

1.读写文本数据

>>>with open ('somefile.txt','rt') as f:
>>>    data = f.read()
>>>#Write chunks of text data
>>>with open('somefile.txt','wt') as f:
>>>    f.write(text1)
>>>    f.write(text2)

类似地,要对文本文件执行写入操作,可以使用open()函数的wt模式来完成,如果待操作的文件已经存在,那么这回清除并覆盖其原先的内容;

如果要在已存在的文件的结尾处追加内容,可以使用open()函数的at模式;

  • 一般来说,读写文本文件都是非常简单直接的,但是,这里了还是有几个微妙的细节需要引起注意;首先,我们在实例中采用了with语句,这会为使用的文件创建一个上下文环境,当程序的控制流离开with语快后,文件将会自动关闭;我们并不一定要用with语句,但是如果我们不用的话请确保要记得手动关闭文件;
>>>f = open('somefile.txt','rt')
>>>data = f.read()
>>>f.close()
  • 关于默认换行符,open()函数提供了一个newline=''的参数;
    with open('somefile.txt','rt',newline = '') as f:

  • 关于文本文件中可能出现的编码错误,当encoding = 'utf-8';
    UnicodeDecodeError:'ascii' codec can't decode byte 0xc3 in position
    如果遇到这样的错误,这通常表示没有一正确的编码方式来读取文件。可以使用encoding来制定不同的编码方式;如果还不能避免的话,则可以为open()函数提供一个可选的errors参数来惨厉错误;

>>>#Replace bad chars with Unicode U+fffd replacement char
>>>f = open(somefile.txt','rt',encoding = 'ascii',errors = 'replace')
>>>f.read()
'Spicy Jalape?o'
>>>#Replace bad chars entirely
>>>f = open(somefile.txt','rt',encoding = 'ascii',errors = 'ignore')
>>>f.read()
'Spicy Jalapeo'

如果常常在摆弄open()函数的encoding和errors参数,并为此做了大量的技巧性操作,那就适得其反了;因为生活本不应该如此艰难,关于文本,第一条守则就是只需要确保总是使用正确的文本编码形式即可;请使用默认的编码设定(通常utf-8)

2.将输出重定向到文件中

问题:我们想把print()函数的输出重定向到一个文件中。

解决方案:我们只需要在print()函数加上file关键字参数即可;

>>>with open('somefile.txt','rt') as f:
>>>    print("hello world!",f)

3.以不同的分隔符或行结尾完成打印

问题:我们想通过print()函数输出数据,但是同时也希望修改分隔符或者行结尾符

解决方案:可以在print()函数中使用sep和end关键字参数来根据需要修改输出;

>>> print('ACME',50,90.4)
ACME 50 90.4
>>> print('ACME',50,90.4,sep=',')
ACME,50,90.4
>>> print('ACME',50,90.4,sep=',',end='!!\n')
ACME,50,90.4!!

我们可以使用end参数在输出中禁止打印出换行符的方式:

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4
>>> for i in range(5):
...     print(i,end=' ')
...
0 1 2 3 4 >>>

str.join 问题也可以处理简单的字符分隔文本问题;

>>> row = ('ACME',50,91.5)
>>> print(','.join(row))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 1: expected str instance, int found
>>> print(','.join(str(w) for w in row))
ACME,50,91.5

更加高效的方法:

>>> print(*row,sep = ',')
ACME,50,91.5

4.对鞋二进制数据

解决方案:使用open()函数的rb模式或者wb模式就可以实现对二进制数据的读或者写;

5.对已不存在的文件执行写入操作

问题:我们想将数据写入到一个文件中,但只当该文件已经不在文件系统中时才这么做;

解决方案:这个问题可以通过使用open()函数中鲜为人知的x模式替换常见的w模式来解决

>>> with open('d:\\tmp.txt','wt') as f:
...     f.write("Hello\n")
...
6
>>> with open('d:\\tmp.txt','xt') as f:
...     f.write("Hello\n")
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'd:\\tmp.txt'

如果文件时二进制模式,那么用xb替代xt即可;

6.在字符串上执行I/O操作

7.读写压缩的数据文件

问题:我们需要读写以gzip、bz2格式压缩的文件中的数据:

解决方案:gzip、bz2,模块使得同这类压缩型文件打交道变得非常简单,这两个模块都提供了open()的其他实现,可用于处理压缩文件;

#gzip compression
>>>import gzip
>>>with gzip.open('somefile.gz','rt') as f:
>>>    text = f.read()

#bz2 compression
>>>import bz2
>>>with bz2.open('somefile.bz2','rt') as f:
>>>    text = f.read()

对应的写入文件也相似;
大部分情况下读写压缩数据都是简单而直接的,单请注意,选择正确的文件模式是至关重要的。如果没有指定的模式,那么默认的模式是二进制,这会使得期望接受文本的程序奔溃。gzip.open()和bz2.open()所接受的参数和内建的open()函数一样,也支持encoding,newline,errors等关键字参数;
当写入压缩数据时,压缩级别可以通过compresslevel关键字参数来指定,这是可选的;

>>>with gzip.open('somefile.gz','wt',compresslevel = 5) as f:
>>>    f.write(text)

默认级别是9,代表着最高的压缩等级。低等级的压缩可带来更好的性能表现,但压缩比就没那么大;

8.对固定大小的记录进行迭代

9.将二进制数据兑取到可变缓冲区中

10.对二进制文件做内存映射

11.处理路径名

问题:我们需要处理路径名以找出基文件名,目录名,绝对路径等相关信息;

解决方案:要操作路径名,可以使用os.path模块中的函数

>>> import os
>>> path = "D:\ostext\meizitu\mzt01\\10a33.jpg"
>>> os.path.basename(path)
'10a33.jpg'
>>> os.path.dirname(path)
'D:\\ostext\\meizitu\\mzt01'
>>> os.path.join('tmp','data',os.path.basename(path))
'tmp\\data\\10a33.jpg'
>>> os.path.expanduser(path)
'D:\\ostext\\meizitu\\mzt01\\10a33.jpg'
#分离扩展名
>>> os.path.splitext(path)
('D:\\ostext\\meizitu\\mzt01\\10a33', '.jpg')

一、python中对文件、文件夹操作时经常用到的os模块和shutil模块常用方法。
1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()
2.返回指定目录下的所有文件和目录名:os.listdir()
3.函数用来删除一个文件:os.remove()
4.删除多个目录:os.removedirs(r“c:\python”)
5.检验给出的路径是否是一个文件:os.path.isfile()
6.检验给出的路径是否是一个目录:os.path.isdir()
7.判断是否是绝对路径:os.path.isabs()
8.检验给出的路径是否真地存:os.path.exists()
9.返回一个路径的目录名和文件名:os.path.split() eg os.path.split('/home/swaroop/byte/code/poem.txt') 结果:('/home/swaroop/byte/code', 'poem.txt')
10.分离扩展名:os.path.splitext()
11.获取路径名:os.path.dirname()
12.获取文件名:os.path.basename()
13.运行shell命令: os.system()
14.读取和设置环境变量:os.getenv() 与os.putenv()
15.给出当前平台使用的行终止符:os.linesep Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'
16.指示你正在使用的平台:os.name 对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'
17.重命名:os.rename(old, new)
18.创建多级目录:os.makedirs(r“c:\python\test”)
19.创建单个目录:os.mkdir(“test”)
20.获取文件属性:os.stat(file)
21.修改文件权限与时间戳:os.chmod(file)
22.终止当前进程:os.exit()
23.获取文件大小:os.path.getsize(filename)



glob是python自己带的一个文件操作相关模块,内容也不多,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索,而且也支持通配符,,?,[]这三个通配符,代表0个或多个字符,?代表一个字符,[]匹配指定范围内的字符,如[0-9]匹配数字。

它的主要方法就是glob,该方法返回所有匹配的文件路径列表,该方法需要一个参数用来指定匹配的路径字符串(本字符串可以为绝对路径也可以为相对路径),比如:

#我这里就是获得C盘下的所有txt文件
>>>import glob
>>>glob.glob(r'c:/*.txt')

#获得指定目录下的所有jpg文件
glob.glob(r'E:/pic/*/*.jpg')

iglob方法

获取一个可编历对象, 使用它可以逐个获取匹配的文件路径名。与glob.glob()的区别是:glob.glob同时获取所有的匹配路径,而 glob.iglob一次只获取一个匹配路径。这有点类似于.NET中操作数据库用到的DataSet与DataReader。下面是一个简单的例子:

import glob     
#父目录中的.py文件  
f = glob.iglob(r'../*.py')  


12.检测文件是否存在

>>>os.path.exists('/etc/passwd')
True
>>>os.path.exists('/etc/spam')
False

#
>>>os.path.isfile('/etc/passwd')
>>>os.path.isdir('/etc/passwd')
>>>os.path.islink('/etc/passwd')
>>>os.path.realpath('/etc/passwd')

#
>>> os.path.getsize(path)
100714
>>> os.path.getmtime(path)
1512957742.67442
>>> import time
>>> time.ctime(os.path.getmtime(path))
'Mon Dec 11 10:02:22 2017'

13.获取目录内容的内部

解决方案:可以使用os.listdir()函数来获取目录中的文件列表;

>>>import os
>>>names = os.listdir(path)

字符串的startswith()和endswith()方法对于筛选目录中的内容也同样有用;
至于文件名的匹配。可以使用glob或者fnmatch()模块;

>>>import glob
>>>pyfiles = glob.glob('somedir/*.py')
#
>>>from fnmatch import fnmatch
>>>pyfiles = [name for name in os.listdir('somedir')]
>>>    if fnmatch(name,'*.py')

14.绕过文件名编码

15.打印无法解码的文件

16.为已经打开的文件添加或修改编码方式

17.将字节写入到文本文件

18.将已有的文件描述符包装为文件对象

19.创建临时文件和目录

20.同串口进行通信

21.序列化Python对象

问题:我们需要将Python对象序列化为字节流,这样就可以保存到文件中,存储到数据库中或者通过网络连接进行传输;

解决方案:序列化数据最常见的做法就是使用pickle模块,其中:要将某个对象转存储到文件中,可以舒勇pickle.dump();如果要从字节流中创建出对象,可以使用peckle.load()或者pickle.loads()函数;

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,993评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,593评论 25 708
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,239评论 2 33
  • lumicinta阅读 325评论 0 0
  • 近两天ps军人形象的人老多,可怜孩子,丑人多作怪不是,p的不像自己就是好看?你得多嫌弃你自己? 爹妈给的就是世界上...
    纵情嬉戏天地间阅读 283评论 0 0