Python 文件 I/O(输入/输出)是比较乏味的事情,因为看不到明显的运行效果,但 I/O 是所有程序都必需的部分,使用输入机制,允许程序读取外部数据(包括来自磁盘、光盘等存储设备的数据),用户输入数据;使用输出机制,允许程序记录运行状态,将程序数据输出到磁盘、光盘等存储设备中;
Python 提供有非常丰富的文件 I/O 支持,它既提供了 pathlib 和 os.path 来操作各种路径,也提供了全局的 open() 函数来打开文件(在打开文件之后,程序既可读取文件的内容,也可向文件输出内容)。而且 Python 提供了多种方式来读取文件内容,因此非常简单、灵活。
此外,在 Python 的 os 模块下也包含了大量进行文件 I/O 的函数,使用这些函数来读取、写入文件也很方便,因此读者可以根据需要选择不同的方式来读写文件。
Pyhon 还提供了 tempfile 模块来创建临时文件和临时目录,tempfile 模块下的高级 API 会自动管理临时文件的创建和删除;当程序不再使用临时文件和临时目录时,程序会自动删除临时文件和临时目录
Windows上的反斜杠以及OS X和Linux上的正斜杠
windows 要用反斜杠转义反斜杠
[root@kube file]# cat demo.py import os myFiles = ['a.txt','b.txt','c.txt'] for i in myFiles: print(os.path.join('/root/python/file', i)) [root@kube file]# py demo.py /root/python/file/a.txt /root/python/file/b.txt /root/python/file/c.txt [root@kube file]#
Python OS 文件/目录方法
os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
序号 | 方法及描述 |
---|---|
1 | os.access(path, mode) 检验权限模式 |
2 | os.chdir(path) 改变当前工作目录 |
3 | os.chflags(path, flags) 设置路径的标记为数字标记。 |
4 | os.chmod(path, mode) 更改权限 |
5 | os.chown(path, uid, gid) 更改文件所有者 |
6 | os.chroot(path) 改变当前进程的根目录 |
7 | os.close(fd) 关闭文件描述符 fd |
8 | os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 |
9 | os.dup(fd) 复制文件描述符 fd |
10 | os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2 |
11 | os.fchdir(fd) 通过文件描述符改变当前工作目录 |
12 | os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。 |
13 | os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。 |
14 | os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。 |
15 | os.fdopen(fd[, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 |
16 | os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。 |
17 | os.fstat(fd) 返回文件描述符fd的状态,像stat()。 |
18 | os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,像 statvfs() |
19 | os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘。 |
20 | os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。 |
21 | os.getcwd() 返回当前工作目录 |
22 | os.getcwdu() 返回一个当前工作目录的Unicode对象 |
23 | os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。 |
24 | os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接 |
25 | os.lchmod(path, mode) 修改连接文件权限 |
26 | os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接。 |
27 | os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src |
28 | os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表。 |
29 | os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 |
30 | os.lstat(path) 像stat(),但是没有软链接 |
31 | os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。 |
32 | os.makedev(major, minor) 以major和minor设备号组成一个原始设备号 |
33 | os.makedirs(path[, mode]) 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。 |
34 | os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。 |
35 | os.mkdir(path[, mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。 |
36 | os.mkfifo(path[, mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制) |
37 | os.mknod(filename[, mode=0600, device]) |
38 | os.open(file, flags[, mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的 |
39 | os.openpty() 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。 |
40 | os.pathconf(path, name) 返回相关文件的系统配置信息。 |
41 | os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 |
42 | os.popen(command[, mode[, bufsize]]) 从一个 command 打开一个管道 |
43 | os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。 |
44 | os.readlink(path) 返回软链接所指向的文件 |
45 | os.remove(path) 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。 |
46 | os.removedirs(path) 递归删除目录。 |
47 | os.rename(src, dst) 重命名文件或目录,从 src 到 dst |
48 | os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名。 |
49 | os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。 |
50 | os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。 |
51 | os.stat_float_times([newvalue]) |
52 | os.statvfs(path) 获取指定路径的文件系统统计信息 |
53 | os.symlink(src, dst) 创建一个软链接 |
54 | os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 |
55 | os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。 |
56 | os.tempnam([dir[, prefix]]) 返回唯一的路径名用于创建临时文件。 |
57 | os.tmpfile() 返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。 |
58 | os.tmpnam() 为创建一个临时文件返回一个唯一的路径 |
59 | os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。 |
60 | os.unlink(path) 删除文件路径 |
61 | os.utime(path, times) 返回指定的path文件的访问和修改的时间。 |
62 | os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) 输出在文件夹中的文件名通过在树中游走,向上或者向下。 |
63 | os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 |
64 | os.path 模块 获取文件的属性信息。 |
input([prompt]) 函数和 raw_input([prompt]) 函数基本类似,但是 input 可以接收一个Python表达式作为输入,并将运算结果返回。
Python open()函数详解:打开指定文件
[root@kube file]# ls a.txt b.txt c.txt demo1.py demo.py qq.txt [root@kube file]# cat demo1.py #coding:utf-8 import os os.remove('qq.txt') os.remove 删除文件
[root@kube file]# py demo1.py [root@kube file]# ll total 8 -rw-r--r-- 1 root root 0 Oct 27 17:54 a.txt -rw-r--r-- 1 root root 0 Oct 27 17:54 b.txt -rw-r--r-- 1 root root 0 Oct 27 17:54 c.txt -rw-r--r-- 1 root root 45 Oct 27 18:11 demo1.py -rw-r--r-- 1 root root 110 Oct 27 17:58 demo.py [root@kube file]#
open() 函数用于创建或打开指定文件,该函数的语法格式如下: file = open(file_name [, mode[, buffering]]) 此格式中,用 [] 括起来的部分,表示作为可选操作,可以使用,也可以省略。其中,各个参数所代表的含义如下: file:表示要创建的文件对象。 file_mode:要创建或打开文件的文件名称,该名称要用引号(单引号或双引号都可以)括起来。需要注意的是,如果要打开的文件和当前执行的代码文件位于同一目录,则直接写文件名即可;否则,此参数需要指定打开文件所在的完整路径。 mode:可选参数,用于指定文件的打开模式。可选的打开模式如表 1 所示。如果不写,则默认以只读(r)模式打开文件。 buffing:可选参数,用于指定对文件做读写操作时,是否使用缓冲区(本节后续会详细介绍)。
open() 函数支持的文件打开模式如表 1 所示。
模式 | 意义 | 注意事项 |
---|---|---|
r | 只读模式打开文件,读文件内容的指针会放在文件的开头。 | 操作的文件必须存在。 |
rb | 以二进制格式、采用只读模式打开文件,读文件内容的指针位于文件的开头,一般用于非文本文件,如图片文件、音频文件等。 | |
r+ | 打开文件后,既可以从头读取文件内容,也可以从开头向文件中写入新的内容,写入的新内容会覆盖文件中等长度的原有内容。 | |
rb+ | 以二进制格式、采用读写模式打开文件,读写文件的指针会放在文件的开头,通常针对非文本文件(如音频文件)。 | |
w | 以只写模式打开文件,若该文件存在,打开时会清空文件中原有的内容。 | 若文件存在,会清空其原有内容(覆盖文件);反之,则创建新文件。 |
wb | 以二进制格式、只写模式打开文件,一般用于非文本文件(如音频文件) | |
w+ | 打开文件后,会对原有内容进行清空,并对该文件有读写权限。 | |
wb+ | 以二进制格式、读写模式打开文件,一般用于非文本文件 | |
a | 以追加模式打开一个文件,对文件只有写入权限,如果文件已经存在,文件指针将放在文件的末尾(即新写入内容会位于已有内容之后);反之,则会创建新文件。 | |
ab | 以二进制格式打开文件,并采用追加模式,对文件只有写权限。如果该文件已存在,文件指针位于文件末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
a+ | 以读写模式打开文件;如果文件存在,文件指针放在文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
ab+ | 以二进制模式打开文件,并采用追加模式,对文件具有读写权限,如果文件存在,则文件指针位于文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
open()文件对象常用的属性
成功打开文件之后,可以调用文件对象本身拥有的属性获取当前文件的部分信息,其常见的属性为:
- file.closed:判断文件是否己经关闭。
- file.mode:返回被打开文件的访问模式。
- file.name:返回文件的名称。
# 以默认方式打开文件 f = open('open_test.py') # 访问文件的编码方式 print(f.encoding) # cp936 # 访问文件的访问模式 print(f.mode) # r # 访问文件是否已经关闭 print(f.closed) # False # 访问文件对象打开的文件名 print(f.name) # open_test.py 上面程序使用 open() 内置函数打开了 open_test.py 文件,接下来程序访问了被打开文件的各属性。运行上面程序,可以看到如下输出结果: cp936 r False open_test.py
file 对象
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
序号 | 方法及描述 |
---|---|
1 | file.close() 关闭文件。关闭后文件不能再进行读写操作。 |
2 | file.flush() 刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。 |
3 | file.fileno() 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。 |
4 | file.isatty() 如果文件连接到一个终端设备返回 True,否则返回 False。 |
5 | file.next() Python 3 中的 File 对象不支持 next() 方法。 返回文件下一行。 |
6 | file.read([size]) 从文件读取指定的字节数,如果未给定或为负则读取所有。 |
7 | file.readline([size]) 读取整行,包括 "\n" 字符。 |
8 | file.readlines([sizeint]) 读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。 |
9 | file.seek(offset[, whence]) 移动文件读取指针到指定位置 |
10 | file.tell() 返回文件当前位置。 |
11 | file.truncate([size]) 从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 Widnows 系统下的换行代表2个字符大小。 |
12 | file.write(str) 将字符串写入文件,返回的是写入的字符长度。 |
13 | file.writelines(sequence) 向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。 |
Python readline()和readlines()函数:按行读取文件
[root@kube file]# cat demo3.py #coding:utf-8 f = open('a.txt','r',True) #打开 a.txt 文件, r 只读形式打开,并且 True 使用 缓存区 while True: line = f.readline() if not line: break print(line) f.close() [root@kube file]# py demo3.py one line two line three line [root@kube file]#
readlines()
[root@kube file]# cat demo3.py #coding:utf-8 f = open('a.txt','r',True) while True: line = f.readlines() #一次读取多行 if not line: break print(line) f.close() [root@kube file]# py demo3.py ['one line\n', 'two line\n', 'three line\n'] [root@kube file]#
Python write()和writelines():向文件中写入数据
[root@kube file]# cat a.txt one line two line three line 写入一行新的数据 [root@kube file]# cat demo4.py #coding:utf-8 f = open('a.txt','a') #以追加模式打开一个文件,对文件只有写入权限,如果文件已经存在,文件指针将放在文件的末尾( f.write('写入一行新的数据\n') f.close() [root@kube file]# cat a.txt one line two line three line 写入一行新的数据 [root@kube file]#
Python writelines()函数
[root@kube file]# cat demo5.py f = open('a.txt', 'r') n = open('b.txt','w+') n.writelines(f.readlines()) n.close() f.close() [root@kube file]#
Python seek()和tell()函数详解
实现对文件指针的移动,文件对象提供了 tell() 函数和 seek() 函数。tell() 函数用于判断文件指针当前所处的位置,而 seek() 函数用于移动文件指针到文件的指定位置
注意,当向文件中写入数据时,如果不是文件的尾部,写入位置的原有数据不会自行向后移动,新写入的数据会将文件中处于该位置的数据直接覆盖掉。
tell() 函数
tell() 函数的用法很简单,其基本语法格式如下:
file.tell()
seek()函数
seek() 函数用于将文件指针移动至指定位置,该函数的语法格式如下: file.seek(offset[, whence]) 其中,各个参数的含义如下: file:表示文件对象; whence:作为可选参数,用于指定文件指针要放置的位置,该参数的参数值有 3 个选择:0 代表文件头(默认值)、1 代表当前位置、2 代表文件尾。 offset:表示相对于 whence 位置文件指针的偏移量,正数表示向后偏移,负数表示向前偏移。例如,当whence == 0 &&offset == 3(即 seek(3,0) ),表示文件指针移动至距离文件开头处 3 个字符的位置;当whence == 1 &&offset == 5(即 seek(5,1) ),表示文件指针向后移动,移动至距离当前位置 5 个字符处。
[root@kube file]# cat demo7.py f = open('a.txt','r') print(f.tell()) f.seek(5) print(f.tell()) f.seek(3,0) print(f.tell()) [root@kube file]# py demo7.py 0 5 3 [root@kube file]#
Python with as用法详解
任何一门编程语言中,文件的输入输出、数据库的连接断开等,都是很常见的资源管理操作。但资源都是有限的,在写程序时,必须保证这些资源在使用过后得到释放,不然就容易造成资源泄露,轻者使得系统处理缓慢,严重时会使系统崩溃。
例如,前面在介绍文件操作时,一直强调打开的文件最后一定要关闭,否则会程序的运行造成意想不到的隐患。但是,即便使用 close() 做好了关闭文件的操作,如果在打开文件或文件操作过程中抛出了异常,还是无法及时关闭文件。
为了更好地避免此类问题,不同的编程语言都引入了不同的机制。在 Python 中,对应的解决方式是使用 with as 语句操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源。
简单的理解,同时包含 __enter__() 和 __exit__() 方法的对象就是上下文管理器。常见构建上下文管理器的方式有 2 种,分别是基于类实现和基于生成器实现,在《 什么是上下文管理器,深入底层了解 with as 语句》一文有详细介绍。
例如,使用 with as 操作已经打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证 with as 语句执行完毕后自动关闭已经打开的文件。
首先学习如何使用 with as 语句。with as 语句的基本语法格式为:
with 表达式 [as target]:
代码块
此格式中,用 [] 括起来的部分可以使用,也可以省略。其中,target 参数用于指定一个变量,该语句会将 expression 指定的结果保存到该变量中。with as 语句中的代码块如果不想执行任何语句,可以直接使用 pass 语句代替
什么是上下文管理器,Python with as底层原理详解
简单的理解,同时包含 __enter__() 和 __exit__() 方法的对象就是上下文管理器。也就是说,上下文管理器必须实现如下两个方法:
- __enter__(self):进入上下文管理器自动调用的方法,该方法会在 with as 代码块执行之前执行。如果 with 语句有 as子句,那么该方法的返回值会被赋值给 as 子句后的变量;该方法可以返回多个值,因此在 as 子句后面也可以指定多个变量(多个变量必须由“()”括起来组成元组)。
- __exit__(self, exc_type, exc_value, exc_traceback):退出上下文管理器自动调用的方法。该方法会在 with as 代码块执行之后执行。如果 with as 代码块成功执行结束,程序自动调用该方法,调用该方法的三个参数都为 None:如果 with as 代码块因为异常而中止,程序也自动调用该方法,使用 sys.exc_info 得到的异常信息将作为调用该方法的参数。
当 with as 操作上下文管理器时,就会在执行语句体之前,先执行上下文管理器的 __enter__() 方法,然后再执行语句体,最后执行 __exit__() 方法。
构建上下文管理器,常见的有 2 种方式:基于类实现和基于生成器实现。
基于类的上下文管理器
通过上面的介绍不难发现,只要一个类实现了 __enter__() 和 __exit__() 这 2 个方法,程序就可以使用 with as 语句来管理它,通过 __exit__() 方法的参数,即可判断出 with 代码块执行时是否遇到了异常。其实,上面程序中的文件对象也实现了这两个方法,因此可以接受 with as 语句的管理。
下面我们自定义一个实现上下文管理协议的类,并尝试用 with as 语句来管理它:
class FkResource: def __init__(self, tag): self.tag = tag print('构造器,初始化资源: %s' % tag) # 定义__enter__方法,with体之前的执行的方法 def __enter__(self): print('[__enter__ %s]: ' % self.tag) # 该返回值将作为as子句中变量的值 return 'fkit' # 可以返回任意类型的值 # 定义__exit__方法,with体之后的执行的方法 def __exit__(self, exc_type, exc_value, exc_traceback): print('[__exit__ %s]: ' % self.tag) # exc_traceback为None,代表没有异常 if exc_traceback is None: print('没有异常时关闭资源') else: print('遇到异常时关闭资源') return False # 可以省略,默认返回None也被看做是False with FkResource('孙悟空') as dr: print(dr) print('[with代码块] 没有异常') print('------------------------------') with FkResource('白骨精'): print('[with代码块] 异常之前的代码') raise Exception print('[with代码块] ~~~~~~~~异常之后的代码') 运行上面的程序,可以看到如下输出结果: 构造器,初始化资源: 孙悟空 [__enter__ 孙悟空]: fkit [with代码块] 没有异常 [__exit__ 孙悟空]: 没有异常时关闭资源 ------------------------------ 构造器,初始化资源: 白骨精 [__enter__ 白骨精]: [with代码块] 异常之前的代码 [__exit__ 白骨精]: 遇到异常时关闭资源 Traceback (most recent call last): File "C:\Users\mengma\Desktop\1.py", line 26, inraise Exception Exception
上面程序定义了一个 FkResource 类,并包含了 __enter__() 和 __exit__() 两个方法,因此该类的对象可以被 with as 语句管理。
此外,程序中两次使用 with as 语句管理 FkResource 对象。第一次代码块没有出现异常,第二次代码块出现了异常。从上面的输出结果来看,使用 with as 语句管理资源,无论代码块是否有异常,程序总可以自动执行 __exit__() 方法。
注意,当出现异常时,如果 __exit__ 返回 False(默认不写返回值时,即为 False),则会重新抛出异常,让 with as 之外的语句逻辑来处理异常;反之,如果返回 True,则忽略异常,不再对异常进行处理。
基于生成器的上下文管理器
除了基于类的上下文管理器,它还可以基于生成器实现。接下来先看一个例子。比如,我们可以使用装饰器 contextlib.contextmanager,来定义自己所需的基于生成器的上下文管理器,用以支持 with as 语句:
from contextlib import contextmanager @contextmanager def file_manager(name, mode): try: f = open(name, mode) yield f finally: f.close() with file_manager('a.txt', 'w') as f: f.write('hello world')
这段代码中,函数 file_manager() 就是一个生成器,当我们执行 with as 语句时,便会打开文件,并返回文件对象 f;当 with 语句执行完后,finally 中的关闭文件操作便会执行。另外可以看到,使用基于生成器的上下文管理器时,不再用定义 __enter__() 和 __exit__() 方法,但需要加上装饰器 @contextmanager,这一点新手很容易疏忽。
需要强调的是,基于类的上下文管理器和基于生成器的上下文管理器,这两者在功能上是一致的。只不过,基于类的上下文管理器更加灵活,适用于大型的系统开发,而基于生成器的上下文管理器更加方便、简洁,适用于中小型程序。但是,无论使用哪一种,不用忘记在方法“__exit__()”或者是 finally 块中释放资源,这一点尤其重要。
Python pickle模块:实现Python对象的持久化存储
Python 中有个序列化过程叫作 pickle,它能够实现任意对象与文本之间的相互转化,也可以实现任意对象与二进制之间的相互转化。也就是说,pickle 可以实现 Python 对象的存储及恢复。
值得一提的是,pickle 是 python 语言的一个标准模块,安装 python 的同时就已经安装了 pickle 库,因此它不需要再单独安装,使用 import 将其导入到程序中,就可以直接使用。
pickle 模块提供了以下 4 个函数供我们使用:
- dumps():将 Python 中的对象序列化成二进制对象,并返回;
- loads():读取给定的二进制对象数据,并将其转换为 Python 对象;
- dump():将 Python 中的对象序列化成二进制对象,并写入文件;
- load():读取指定的序列化数据文件,并返回对象。
以上这 4 个函数可以分成两类,其中 dumps 和 loads 实现基于内存的 Python 对象与二进制互转;dump 和 load 实现基于文件的 Python 对象与二进制互转。
pickle.dumps()函数 此函数用于将 Python 对象转为二进制对象,其语法格式如下: dumps(obj, protocol=None, *, fix_imports=True) 此格式中各个参数的含义为: obj:要转换的 Python 对象; protocol:pickle 的转码协议,取值为 0、1、2、3、4,其中 0、1、2 对应 Python 早期的版本,3 和 4 则对应 Python 3.x 版本及之后的版本。未指定情况下,默认为 3。 其它参数:为了兼容 Python 2.x 版本而保留的参数,Python 3.x 中可以忽略。
[root@kube file]# cat demo9.py #coding:utf-8 import pickle tup1 = ('test pickle',[1,2,3],None) p1 = pickle.dumps(tup1) print(p1) [root@kube file]# py demo9.py b'\x80\x03X\x0b\x00\x00\x00test pickleq\x00]q\x01(K\x01K\x02K\x03eN\x87q\x02.' [root@kube file]#
pickle.loads()函数 此函数用于将二进制对象转换成 Python 对象,其基本格式如下: loads(data, *, fix_imports=True, encoding='ASCII', errors='strict') 其中,data 参数表示要转换的二进制对象,其它参数只是为了兼容 Python 2.x 版本而保留的,可以忽略。
[root@kube file]# cat demo9.py #coding:utf-8 import pickle tup1 = ('test pickle',[1,2,3],None) p1 = pickle.dumps(tup1) t2 = pickle.loads(p1) print(t2) [root@kube file]# py demo9.py ('test pickle', [1, 2, 3], None) [root@kube file]#
pickle.dump()函数 此函数用于将 Python 对象转换成二进制文件,其基本语法格式为: dump (obj, file,protocol=None, *, fix mports=True) 其中各个参数的具体含义如下: obj:要转换的 Python 对象。 file:转换到指定的二进制文件中,要求该文件必须是以"wb"的打开方式进行操作。 protocol:和 dumps() 函数中 protocol 参数的含义完全相同,因此这里不再重复描述。 其他参数:为了兼容以前 Python 2.x版本而保留的参数,可以忽略。
[root@kube file]# cat demo10.py import pickle tup1 = ('I love Python', {1,2,3}, None) #使用 dumps() 函数将 tup1 转成 p1 with open ("test.txt", 'wb') as f: #打开文件 pickle.dump(tup1, f) #用 dump 函数将 Python 对象转成二进制对象文件 [root@kube file]# cat test.txt I love Pythonqcbuiltins set q]q(KKKeqRqNq.[root@kube file]# Xshell
pickle.load()函数 此函数和 dump() 函数相对应,用于将二进制对象文件转换成 Python 对象。该函数的基本语法格式为: load(file, *, fix_imports=True, encoding='ASCII', errors='strict') 其中,file 参数表示要转换的二进制对象文件(必须以 "rb" 的打开方式操作文件),其它参数只是为了兼容 Python 2.x 版本而保留的参数,可以忽略。
[root@kube file]# cat demo11.py import pickle tup1 = ('I love Python', {1,2,3}, None) #使用 dumps() 函数将 tup1 转成 p1 with open ("a.txt", 'wb') as f: #打开文件 pickle.dump(tup1, f) #用 dump 函数将 Python 对象转成二进制对象文件 with open ("a.txt", 'rb') as f: #打开文件 t3 = pickle.load(f) #将二进制文件对象转换成 Python 对象 print(t3) [root@kube file]# py demo11.py ('I love Python', {1, 2, 3}, None) [root@kube file]#
Python fileinput模块:逐行读取多个文件
fileinput 模块提供了 input 函数,可以把多个输入流合并在一起,该函数的语法格式如下:
fileinput.input(files="filename1, filename2, ...", inplace=False, backup='', bufsize=0, mode='r', openhook=None)
此函数会返回一个 FileInput 对象,其中,各个参数的含义如下:
- files:多个文件的路径列表;
- inplace:用于指定是否将标准输出的结果写回到文件,此参数默认值为 False;
- backup:用于指定备份文件的扩展名;
- bufsize:指定缓冲区的大小,默认为 0;
- mode:打开文件的格式,默认为 r(只读格式);
- openhook:控制文件的打开方式,例如编码格式等。
当程序使用上面函数创建了 FileInput 对象之后,即可通过 for 循环来遍历文件的每一行。此外,fileinput 还提供了很多全局函数来判断正在读取的文件信息,如表 1 所示。
函数名 | 功能描述 |
---|---|
fileinput.filename() | 返回正在读取的文件的文件名。 |
fileinput.fileno() | 返回当前文件的文件描述符(file descriptor),该文件描述符是一个整数。 |
fileinput.lineno() | 返回当前读取的行号。 |
fileinput.filelineno() | 返回当前读取的行在其文件中的行号。 |
fileinput.isfirstline() | 返回当前读取的行在其文件中是否为第一行。 |
fileinput.isstdin() | 返回最后一行是否从 sys.stdin 读取。程序可以使用“-”代表从 sys.stdin 读取。 |
fileinput.nextfile() | 关闭当前文件,开始读取下一个文件。 |
fileinput.close() | 关闭 FileInput 对象。 |
文件描述符是一个文件的代号,其值为一个整数。后续章节将会介绍关于文件描述符的操作。
[root@kube file]# cat a.txt one line two line three line [root@kube file]# cat b.txt one line two line three line 写入一行新的数据 [root@kube file]# cat demo12.py import fileinput # 一次读取多个文件 for line in fileinput.input(files=('a.txt', 'b.txt')): # 输出文件名,当前行在当前文件中的行号 print(fileinput.filename(), fileinput.filelineno(), line) # 关闭文件流 fileinput.close() [root@kube file]# py demo12.py a.txt 1 one line a.txt 2 two line a.txt 3 three line b.txt 1 one line b.txt 2 two line b.txt 3 three line b.txt 4 写入一行新的数据 [root@kube file]#
Python linecache模块用法:随机读取文件指定行
linecache 模块允许从 Python 源文件中随机读取指定行,并在内部使用缓存优化存储。由于该模块主要被设计成读取 Python 源文件,因此它会用 UTF-8 字符集来读取文本文件。 实际上,使用 linecache 模块也可以读取其他文件,只要该文件使用了 UTF-8 字符集存储。 linecache 模块包含以下常用函数: linecache.getline(filename, lineno, module_globals=None):读取指定模块中指定文件的指定行。其中 filename 指定文件名,lineno 指定行号。 linecache.clearcache():清空缓存。 linecache.checkcache(filename=None):检查缓存是否有效。如果没有指定 filename 参数,则默认检查所有缓存的数据。
import linecache import random # 读取random模块的源文件的第3行 print(linecache.getline(random.__file__, 3)) # 读取本程序的第3行 print(linecache.getline('linecache_test.py', 3)) # 读取普通文件的第2行 print(linecache.getline('utf_text.txt', 2))
Python pathlib模块用法详解
PurePath类的属性和方法
PurePath 提供了不少属性和方法(如表 1 所示),这些属性和方法主要还是用于操作路径字符串。由于 PurePath 并不真正执行底层的文件操作,也不理会路径字符串在底层是否有对应的路径,因此这些操作有点类似于字符串方法。
类属性和方法名 | 功能描述 |
PurePath.parts | 该属性返回路径字符串中所包含的各部分。 |
PurePath.drive | 该属性返回路径字符串中的驱动器盘符。 |
PurePath.root | 该属性返回路径字符串中的根路径。 |
PurePath.anchor | 该属性返回路径字符串中的盘符和根路径。 |
PurePath.parents | 该属性返回当前路径的全部父路径。 |
PurPath.parent | 该属性返回当前路径的上一级路径,相当于 parents[0] 的返回值。 |
PurePath.name | 该属性返回当前路径中的文件名。 |
PurePath.suffixes | 该属性返回当前路径中的文件所有后缀名。 |
PurePath.suffix | 该属性返回当前路径中的文件后缀名。相当于 suffixes 属性返回的列表的最后一个元素。 |
PurePath.stem | 该属性返回当前路径中的主文件名。 |
PurePath.as_posix() | 将当前路径转换成 UNIX 风格的路径。 |
PurePath.as_uri() | 将当前路径转换成 URI。只有绝对路径才能转换,否则将会引发 ValueError。 |
PurePath.is_absolute() | 判断当前路径是否为绝对路径。 |
PurePath.joinpath(*other) | 将多个路径连接在一起,作用类似于前面介绍的斜杠运算符。 |
PurePath.match(pattern) | 判断当前路径是否匹配指定通配符。 |
PurePath.relative_to(*other) | 获取当前路径中去除基准路径之后的结果。 |
PurePath.with_name(name) | 将当前路径中的文件名替换成新文件名。如果当前路径中没有文件名,则会引发 ValueError。 |
PurePath.with_suffix(suffix) | 将当前路径中的文件后缀名替换成新的后缀名。如果当前路径中没有后缀名,则会添加新的后缀名。 |
下面程序大致测试了上面属性和方法的用法:
from pathlib import * # 访问drive属性 print(PureWindowsPath('c:/Program Files/').drive) # c: print(PureWindowsPath('/Program Files/').drive) # '' print(PurePosixPath('/etc').drive) # '' # 访问root属性 print(PureWindowsPath('c:/Program Files/').root) # \ print(PureWindowsPath('c:Program Files/').root) # '' print(PurePosixPath('/etc').root) # / # 访问anchor属性 print(PureWindowsPath('c:/Program Files/').anchor) # c:\ print(PureWindowsPath('c:Program Files/').anchor) # c: print(PurePosixPath('/etc').anchor) # / # 访问parents属性 pp = PurePath('abc/xyz/wawa/haha') print(pp.parents[0]) # abc\xyz\wawa print(pp.parents[1]) # abc\xyz print(pp.parents[2]) # abc print(pp.parents[3]) # . # 访问parent属性 print(pp.parent) # abc\xyz\wawa # 访问name属性 print(pp.name) # haha pp = PurePath('abc/wawa/bb.txt') print(pp.name) # bb.txt pp = PurePath('abc/wawa/bb.txt.tar.zip') # 访问suffixes属性 print(pp.suffixes[0]) # .txt print(pp.suffixes[1]) # .tar print(pp.suffixes[2]) # .zip # 访问suffix属性 print(pp.suffix) # .zip print(pp.stem) # bb.txt.tar pp = PurePath('abc', 'xyz', 'wawa', 'haha') print(pp) # abc\xyz\wawa\haha # 转成Unix风格的路径 print(pp.as_posix()) # abc/xyz/wawa/haha # 将相对路径转换成Uri引发异常 #print(pp.as_uri()) # ValueError # 创建绝对路径 pp = PurePath('d:/', 'Python', 'Python3.6') # 将绝对路径转换成Uri print(pp.as_uri()) # file:///d:/Python/Python3.6 # 判断当前路径是否匹配指定模式 print(PurePath('a/b.py').match('*.py')) # True print(PurePath('/a/b/c.py').match('b/*.py')) # True print(PurePath('/a/b/c.py').match('a/*.py')) # False pp = PurePosixPath('c:/abc/xyz/wawa') # 测试relative_to方法 print(pp.relative_to('c:/')) # abc\xyz\wawa print(pp.relative_to('c:/abc')) # xyz\wawa print(pp.relative_to('c:/abc/xyz')) # wawa # 测试with_name方法 p = PureWindowsPath('e:/Downloads/pathlib.tar.gz') print(p.with_name('fkit.py')) # e:\Downloads\fkit.py p = PureWindowsPath('c:/') #print(p.with_name('fkit.py')) # ValueError # 测试with_suffix方法 p = PureWindowsPath('e:/Downloads/pathlib.tar.gz') print(p.with_suffix('.zip')) # e:\Downloads\pathlib.tar.zip p = PureWindowsPath('README') print(p.with_suffix('.txt')) # README.txt
Python os.path模块常见函数用法(实例+详细注释)
os.path 模块下提供了一些操作目录的方法,这些函数可以操作系统的目录本身。例如,该模块提供了 exists() 函数判断该目录是否存在,也提供了 getctime()、getmtime()、getatime() 函数来获取该目录的创建时间、最后一次修改时间、最后一次访问时间,还提供了 getsize() 函数来获取指定文件的大小。
下面程序示范了 os.path 模块下的操作目录的常见函数的功能和用法:
import os import time # 获取绝对路径 print(os.path.abspath("abc.txt")) # G:\publish\codes\12\12.2\abc.txt # 获取共同前缀 print(os.path.commonprefix(['/usr/lib', '/usr/local/lib'])) # /usr/l # 获取共同路径 print(os.path.commonpath(['/usr/lib', '/usr/local/lib'])) # \usr # 获取目录 print(os.path.dirname('abc/xyz/README.txt')) #abc/xyz # 判断指定目录是否存在 print(os.path.exists('abc/xyz/README.txt')) # False # 获取最近一次访问时间 print(time.ctime(os.path.getatime('os.path_test.py'))) # 获取最后一次修改时间 print(time.ctime(os.path.getmtime('os.path_test.py'))) # 获取创建时间 print(time.ctime(os.path.getctime('os.path_test.py'))) # 获取文件大小 print(os.path.getsize('os.path_test.py')) # 判断是否为文件 print(os.path.isfile('os.path_test.py')) # True # 判断是否为目录 print(os.path.isdir('os.path_test.py')) # False # 判断是否为同一个文件 print(os.path.samefile('os.path_test.py', './os.path_test.py')) # True
运行上面程序,大部分函数的输出结果都通过注释给出了,程序中 getatime()、getmtime()、getctime() 三个函数分别获取了文件的最后一次访问时间、最后一次修改时间和创建时间。读者可通过运行该程序来理解 os.path 模块下这些函数的功能。
Python fnmatch模块:用于文件名的匹配
前面介绍的那些操作目录的函数只能进行简单的模式匹配,但 fnmatch 模块可以支持类似于 UNIX shell 风格的文件名匹配。
fnmatch 匹配支持如下通配符:
- *:可匹配任意个任意字符。
- ?:可匹配一个任意字符。
- [字符序列]:可匹配中括号里字符序列中的任意字符。该字符序列也支持中画线表示法。比如[a-c]可代表a、b 和 c 字符中任意一个。
- [!字符序列]:可匹配不在中括号里字符序列中的任意字符。
在该模块下提供了如下函数:
- fnmatch.fnmatch(filename, pattern):判断指定文件名是否匹配指定 pattern。如下程序示范了 fnmatch() 函数的用法:
[root@kube file]# cat demo15.py from pathlib import * import fnmatch # 遍历当前目录下所有文件和子目录 for file in Path('.').iterdir(): # 访问所有以_test.py结尾的文件 if fnmatch.fnmatch(file, '*_test.py'): print(file) [root@kube file]# py demo15.py test_test.py [root@kube file]#
Python os模块详解
os模块与目录相关的函数
与目录相关的函数如下:
- os.getcwd():获取当前目录。
- os.chdir(path):改变当前目录。
- os.fchdir(fd):通过文件描述利改变当前目录。该函数与上一个函数的功能基本相似,只是该函数以文件描述符作为参数来代表目录。
[root@kube file]# cat demo16.py import os # 获取当前目录 print(os.getcwd()) # 改变当前目录 os.chdir('../random') # 再次获取当前目录 print(os.getcwd()) [root@kube file]# py demo16.py /root/python/file /root/python/random [root@kube file]#
- 上面程序示范了使用 getcwd() 来获取当前目录,也示范了使用 chdir() 来改变当前目录。
- os.chroot(path):改变当前进程的根目录。
- os.listdir(path):返回 path 对应目录下的所有文件和子目录。
- os.mkdir(path[, mode]):创建 path 对应的目录,其中 mode 用于指定该目录的权限。该 mode参数代表一个 UNIX 风格的权限,比如 0o777 代表所有者可读/可写/可执行、组用户可读/可写/可执行、其他用户可读/可写/可执行。
- os.makedirs(path[, mode]):其作用类似于 mkdir(),但该函数的功能更加强大,它可以边归创建目录。比如要创建 abc/xyz/wawa 目录,如果在当前目录下没有 abc 目录,那么使用 mkdir() 函数就会报错,而使用 makedirs() 函数则会先创建 abc,然后在其中创建 xyz 子目录,最后在 xyz 子目录下创建 wawa 子目录。
[root@kube file]# cat demo17.py import os path = 'my_dir' # 直接在当前目录下创建目录 os.mkdir(path, 0o755) path = "abc/xyz/wawa" # 递归创建目录 os.makedirs(path, 0o755) [root@kube file]#
os模块与权限相关的函数
与权限相关的函数如下:
- os.access(path, mode):检查 path 对应的文件或目录是否具有指定权限。该函数的第二个参数可能是以下四个状态值的一个或多个值:
- os.F_OK:判断是否存在。
- os.R_OK:判断是否可读。
- os.W_OK:判断是否可写。
- os.X_OK:判断是否可执行。
import os # 判断当前目录的权限 ret = os.access('.', os.F_OK|os.R_OK|os.W_OK|os.X_OK) print("os.F_OK|os.R_OK|os.W_OK|os.X_OK - 返回值:", ret) # 判断os.access_test.py文件的权限 ret = os.access('os.access_test.py', os.F_OK|os.R_OK|os.W_OK) print("os.F_OK|os.R_OK|os.W_OK - 返回值:", ret)
os模块与文件访问相关的函数
与文件访问相关的函数如下:
os.open(file, flags[, mode]):打开一个文件,并且设置打开选项,mode 参数是可选的。该函数返回文件描述符。其中 flags 代表打开文件的旗标,它支持如下一个或多个选项:
os.O_RDONLY:以只读的方式打开。
os.O_WRONLY:以只写的方式打开。
os.O_RDWR:以读写的方式打开。
os.O_NONBLOCK:打开时不阻塞。
os.O_APPEND:以追加的方式打开。
os.O_CREAT:创建并打开一个新文件。
os.O_TRUNC:打开一个文件并截断它的长度为0(必须有写权限)。
os.O_EXCL:在创建文件时,如果指定的文件存在,则返回错误。
os.O_SHLOCK:自动获取共享锁。
os.O_EXLOCK:自动获取独立锁。
os.O_DIRECT:消除或减少缓存效果。
os.O_FSYNC:同步写入。
os.O_NOFOLLOW:不追踪软链接。
os.read(fd, n):从文件描述符 fd 中读取最多 n 个字节,返回读到的字符串。如果文件描述符副对应的文件己到达结尾,则返回一个空字节串。
os.write(fd, str):将字节串写入文件描述符 fd 中,返回实际写入的字节串长度。
os.close(fd):关闭文件描述符 fd。
os.lseek(fd, pos, how):该函数同样用于移动文件指针。其中 how 参数指定从哪里开始移动,如果将 how 设为 0 或 SEEK_SET,则表明从文件开头开始移动;如果将 how 设为 1 或 SEEK_CUR,则表明从文件指针当前位置开始移动;如果将 how 设为 2 或 SEEK_END,则表明从文件结束处开始移动。上面几个函数同样可用于执行文件的读写,程序通常会先通过 os.open() 打开文件,然后调用 os.read()、os.write() 来读写文件,当操作完成后通过 os.close() 关闭文件。
import os # 以读写、创建方式打开文件 f = os.open('abc.txt', os.O_RDWR|os.O_CREAT) # 写入文件内容 len1 = os.write(f, '水晶潭底银鱼跃,\n'.encode('utf-8')) len2 = os.write(f, '清徐风中碧竿横。\n'.encode('utf-8')) # 将文件指针移动到开始处 os.lseek(f, 0, os.SEEK_SET) # 读取文件内容 data = os.read(f, len1 + len2) # 打印读取到字节串 print(data) # 将字节串恢复成字符串 print(data.decode('utf-8')) os.close(f)
Python tempfile模块:生成临时文件和临时目录
tempfile 模块中常用的函数,如表 1 所示。
tempfile 模块函数 | 功能描述 |
---|---|
tempfile.TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None) | 创建临时文件。该函数返回一个类文件对象,也就是支持文件 I/O。 |
tempfile.NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True) | 创建临时文件。该函数的功能与上一个函数的功能大致相同,只是它生成的临时文件在文件系统中有文件名。 |
tempfile.SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None) | 创建临时文件。与 TemporaryFile 函数相比,当程序向该临时文件输出数据时,会先输出到内存中,直到超过 max_size 才会真正输出到物理磁盘中。 |
tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None) | 生成临时目录。 |
tempfile.gettempdir() | 获取系统的临时目录。 |
tempfile.gettempdirb() | 与 gettempdir() 相同,只是该函数返回字节串。 |
tempfile.gettempprefix() | 返回用于生成临时文件的前缀名。 |
tempfile.gettempprefixb() | 与 gettempprefix() 相同,只是该函数返回字节串。 |
提示:表中有些函数包含很多参数,但这些参数都具有自己的默认值,因此如果没有特殊要求,可以不对其传参。
tempfile 模块还提供了 tempfile.mkstemp() 和 tempfile.mkdtemp() 两个低级别的函数。上面介绍的 4 个用于创建临时文件和临时目录的函数都是高级别的函数,高级别的函数支持自动清理,而且可以与 with 语句一起使用,而这两个低级别的函数则不支持,因此一般推荐使用高级别的函数来创建临时文件和临时目录。
此外,tempfile 模块还提供了 tempfile.tempdir 属性,通过对该属性赋值可以改变系统的临时目录。
[root@kube file]# cat demo18.py import tempfile # 创建临时文件 fp = tempfile.TemporaryFile() print(fp.name) fp.write('两情若是久长时,'.encode('utf-8')) fp.write('又岂在朝朝暮暮。'.encode('utf-8')) # 将文件指针移到开始处,准备读取文件 fp.seek(0) print(fp.read().decode('utf-8')) # 输出刚才写入的内容 # 关闭文件,该文件将会被自动删除 fp.close() # 通过with语句创建临时文件,with会自动关闭临时文件 with tempfile.TemporaryFile() as fp: # 写入内容 fp.write(b'I Love Python!') # 将文件指针移到开始处,准备读取文件 fp.seek(0) # 读取文件内容 print(fp.read()) # b'I Love Python!' # 通过with语句创建临时目录 with tempfile.TemporaryDirectory() as tmpdirname: print('创建临时目录', tmpdirname) [root@kube file]# py demo18.py 3 两情若是久长时,又岂在朝朝暮暮。 b'I Love Python!' 创建临时目录 /tmp/tmp78v4e5j7 [root@kube file]#
上面程序以两种方式来创建临时文件:
- 第一种方式是手动创建临时文件,读写临时文件后需要主动关闭它,当程序关闭该临时文件时,该文件会被自动删除。
- 第二种方式则是使用 with 语句创建临时文件,这样 with 语句会自动关闭临时文件。
上面程序最后还创建了临时目录。由于程序使用 with 语句来管理临时目录,因此程序也会自动删除该临时目录。
上面第一行输出结果就是程序生成的临时文件的文件名,最后一行输出结果就是程序生成的临时目录的目录名。需要注意的是,不要去找临时文件或临时文件夹,因为程序退出时该临时文件和临时文件夹都会被删除。