Python文件操作 I/O

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])
创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。

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])
决定stat_result是否以float对象显示时间戳

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 所示。

 

表 1 open 函数支持的文件打开模式
模式意义注意事项
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])

读取整行,包括 " " 字符。

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
', 'two line
', 'three line
']
[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('写入一行新的数据
')

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__() 方法的对象就是上下文管理器。也就是说,上下文管理器必须实现如下两个方法:

  1. __enter__(self):进入上下文管理器自动调用的方法,该方法会在 with as 代码块执行之前执行。如果 with 语句有 as子句,那么该方法的返回值会被赋值给 as 子句后的变量;该方法可以返回多个值,因此在 as 子句后面也可以指定多个变量(多个变量必须由“()”括起来组成元组)。
  2. __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:UsersmengmaDesktop1.py", line 26, in <module>
    raise 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 个函数供我们使用:

  1. dumps():将 Python 中的对象序列化成二进制对象,并返回;
  2. loads():读取给定的二进制对象数据,并将其转换为 Python 对象;
  3. dump():将 Python 中的对象序列化成二进制对象,并写入文件;
  4. 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'x80x03Xx0bx00x00x00test pickleqx00]qx01(Kx01Kx02Kx03eNx87qx02.'
[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 所示。

表 1 fileinput 模块常用函数
函数名功能描述
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 并不真正执行底层的文件操作,也不理会路径字符串在底层是否有对应的路径,因此这些操作有点类似于字符串方法。

表 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]) # abcxyzwawa
print(pp.parents[1]) # abcxyz
print(pp.parents[2]) # abc
print(pp.parents[3]) # .
# 访问parent属性
print(pp.parent) # abcxyzwawa
# 访问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) # abcxyzwawahaha
# 转成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:/'))  # abcxyzwawa
print(pp.relative_to('c:/abc'))  # xyzwawa
print(pp.relative_to('c:/abc/xyz'))  # wawa
# 测试with_name方法
p = PureWindowsPath('e:/Downloads/pathlib.tar.gz')
print(p.with_name('fkit.py')) # e:Downloadsfkit.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:Downloadspathlib.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:publishcodes1212.2abc.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, '水晶潭底银鱼跃,
'.encode('utf-8'))
len2 = os.write(f, '清徐风中碧竿横。
'.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 所示。

表 1 tempfile 模块常用函数及功能
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]# 

上面程序以两种方式来创建临时文件:

  1. 第一种方式是手动创建临时文件,读写临时文件后需要主动关闭它,当程序关闭该临时文件时,该文件会被自动删除。
  2. 第二种方式则是使用 with 语句创建临时文件,这样 with 语句会自动关闭临时文件。


上面程序最后还创建了临时目录。由于程序使用 with 语句来管理临时目录,因此程序也会自动删除该临时目录。

 上面第一行输出结果就是程序生成的临时文件的文件名,最后一行输出结果就是程序生成的临时目录的目录名。需要注意的是,不要去找临时文件或临时文件夹,因为程序退出时该临时文件和临时文件夹都会被删除。

原文地址:https://www.cnblogs.com/zy09/p/11748372.html