9. 文件操作¶
文件操作是编程语言提供的最基本的功能,如果数据不能以文件形式存储在存储介质上,比如硬盘,那么信息就不能长期存储,也无法共享和传输。
Python 提供了强大的文件操作方法。操作系统不允许用户程序直接访问磁盘,而是要通过文件系统调用,Python 通过 C 函数库访问系统调用,进行文件读写。对文件读写操作需要通过文件描述符进行。
9.1. 文件打开和关闭¶
9.1.1. 文件打开模式¶
打开文件获取文件描述符,打开文件时需要指定对文件的读写模式,和写追加模式。常见的文件模式如下:
模式 描述 ‘r’ 以只读方式打开文件(默认),不存在报错 FileNotFoundError ‘w’ 以写方式打开文件,如果文件存在,首先清空原内容,如果不存在先创建文件 ‘x’ 以写方式打开文件,如果文件存在,则报错 FileExistsError ‘a’ 以写方式打开文件,并追加内容到文件结尾,如果文件不能存在则先创建文件 ‘+’ 可同时读写
‘+’ 模式可以和其他模式组合,以同时支持读写,常用组合和特性如下:
打开模式 r r+ w w+ a a+ 可读
可写
创建
覆盖
指针在开始
指针在结尾
数据流在读写时又分为两种转换模式:
模式 描述 ‘b’ 二进制模式(不转换) ‘t’ 文本模式(转换,默认)
二进制模式将内存中的数据信息直接写入到文件中,不做任何转换。如内存中的数据 0x01 以二进制写入就是直接写入 0x01 到文件中。
而文本模式是为解决操作系统兼容性引入的。
在文本中,有一些字符不是是用来显示的,而是用来控制的,称为控制符,比如告诉编辑器一行结束就是字符 ‘\n’, 对应 ASCII 码 0x0d,但是不同的操作系统使用的控制符并不一致,这导致在A平台下编辑的文件到B平台下可能就无法正常显示。
类 Unix 操作系统采用单个 ‘\n’ 表示行结束符。Windows 使用两个字符 “\r\n” 表示。而 Mac 系统使用 ‘\r’ 表示。
所以当指明使用文本模式读取时,如果是在 Winodows 系统,那么当读取到 “\r\n” 或者 ‘\r’ 时就会转换为 “\r\n” ,写的时候会将 ‘n’ 转换为 “\r\n”。 如果是进行文本编辑,那么应该使用默认的文本打开模式,如果是多媒体等格式的文件就要使用二进制模式,以保证读取和写入的数据是一致的。 参见 Windows 上的 fopen 手册。
在类 Unix 系统上这两种模式是等价的,也即均为 ‘b’ 模式,遵循 POSIX 标准的 C 库函数不会对数据进行任何转换,而把这些处理交给用户空间的编辑器。
open(file, mode='r', buffering=-1, encoding=None, errors=None,
newline=None, closefd=True, opener=None)
Open file and return a stream. Raise IOError upon failure.
在 Python 中,和 c 接口中的意义有所不同,只有 ‘b’ 模式,且并不作为转换模式使用,而是指定参数的类型:指定了 ‘b’ 模式,那么写入参数必须是 bytes 类型,同样读取返回的也是 bytes 类型:
0 1 2 3 4 5 6 7 8 | # 'b' 模式中,write 参数必须是 bytes 类型的
with open('test.txt', 'wb') as fw:
fw.write('一abc')
# 正确写入方式为
# fw.write(bytes('一abc', encoding='utf-8'))
>>>
TypeError: a bytes-like object is required, not 'str'
|
同样读取时如果指定了 ‘b’ 模式,则返回 bytes 类型:
0 1 2 3 4 | with open('wb.txt', 'rb') as fr:
print(fr.read())
>>>
b'\xe4\xb8\x80abc'
|
通常对文件操作时应该明确指定编码格式,例如:
0 1 2 3 4 5 6 7 8 9 10 11 | def test_file_encode():
with open('wb.txt', 'w', encoding='utf-8') as fw:
fw.write('一abc') # 非 'b' 模式可以直接写入字符串
# 如果此处打开模式为 'rb' 则 fr.read() 返回 bytes 类型
with open('wb.txt', 'r', encoding='utf-8') as fr:
print(fr.read()) # 自动使用 encoding 参数进行解码
test_file_encode()
>>>
一abc
|
可以通过 hexdump 查看写出的文件内容:
0 1 2 | # hexdump 查看写出文件,可以发现前三个字节为 '一' 的 unicode 码值的 utf-8 编码
$ hexdump -C wb.txt
00000000 e4 b8 80 61 62 63 |...abc|
|
9.1.2. 指定文件编码¶
open() 函数实现文件的打开,它返回一个文件描述符,在 Python 里它是一个文件对象。
0 1 2 3 4 5 6 7 8 | f = open("test.txt", 'r')
print(f)
>>>
# Windows 运行结果
<_io.TextIOWrapper name='test.txt' mode='r' encoding='cp936'>
# Linux 运行结果
<_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>
|
这里之所以打印文件对象,是要查看编码,发现在不同的平台上它的值是不同的,该参数可以在打开文件时指定,如果不指定,则使用 locale.getpreferredencoding() 获取。 它用于文本模式时如何解码读取的文件数据,或者如何编码写入到文件。关于编码格式参考 常见的编码方式 。
0 1 2 3 | print(locale.getpreferredencoding(False))
>>>
cp936
|
cp936 编码,也即 GBK 编码,所以在 Windows 上默认读写文件使用该编码方式,在 Linux 上则是 UTF-8。那么相同的文件,由于解码不同,就会读取出错,写入也一样。
为了能够正确读取文件,应该指明要读写的文件的编码方式,通常我们使用 UTF-8 编码来保存中文文档。Python3.7 版本后,locale.getpreferredencoding() 总是返回 UTF-8,以和 Python 默认编码保持一致,不再依赖于系统环境。
0 1 2 3 4 | f = open("test.txt", 'r', encoding='UTF-8')
print(f)
>>>
<_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>
|
当完成读写操作后,应关闭文件描述符,以将缓存数据写入磁盘,并释放系统资源,这非常简单:
0 | f.close()
|
9.1.3. 文件描述符的属性¶
在 Python 中,文件描述符就是一个文件对象,它具有如下属性:
属性 描述 file.closed 返回布尔值,True 已被关闭。 file.mode 返回被打开文件的访问模式。 file.name 返回文件的名称。
0 1 2 3 4 5 6 7 | f = open("test.txt", 'r', encoding="UTF-8")
print ("name: %s, closed: %s, mode:'%s'" % (f.name, f.closed, f.mode))
f.close()
print ("name: %s, closed: %s, mode:'%s'" % (f.name, f.closed, f.mode))
>>>
name: test.txt, closed: False, mode:'r'
name: test.txt, closed: True, mode:'r'
|
9.2. 文件对象内建方法¶
按功能划分文件对象内建方法:
- 关闭
- file.close() 关闭文件。
- 读取
- file.read([size=-1]) 从文件读取指定的字节数,如未指定或为负则读取所有,返回读取数据,无数据时返回空字符串 ‘’。
- file.readline([size=-1]) 读取一行含换行符,如指定正整数,则最多返回 size 个字符。
- file.readlines([hint=-1]) 读取所有行以列表返回,如指定整数,至少读取 hint 个字符,确保最后读取的行是完整的。
- 写入和截断
- file.write(str) 将字符串写入文件,返回写入的字符长度。
- file.writelines(sequence) 向文件写入字符串序列(必须是字符串序列),比如列表,元组,如需要换行需自行加入换行符。
- file.flush() 刷新缓冲区数据到文件。
- file.truncate([size]) 截断文件,截断文件指针偏移处之后数据,如指定正整数,则把文件截断为 size 字节,不影响指针偏移。
- 文件指针偏移
- file.seek(offset[, whence]) 移动文件指针到指定偏移位置。如指定参数 whence,则移动偏移相对于 0 文件开始, 1 当前位置, 2 文件末尾。
- file.tell() 返回文件指针偏移位置。
- 文件描述符
- file.fileno() 返回整型文件描述符,用于 os 模块方法。
- 判定
- file.isatty() 如果文件连接到一个终端设备返回 True。
注意
任何对文件的读取和写入动作,都会自动改变文件的指针偏移位置。
0 1 2 3 4 5 6 | with open("sample.py", 'r') as f:
data = f.read()
data = f.read()
print(repr(data))
>>>
''
|
9.3. 文件或目录常用操作¶
9.3.1. 文件或目录创建删除¶
9.3.1.1. 创建删除文件¶
普通文件使用 open() 写模式即可创建。对应的删除方法为 os.remove()。
0 1 2 3 4 5 | fname = "test.txt"
with open(fname, 'w'):
pass
os.remove(fname) # 删除当前目录下 test.txt 文件
os.unlink(fname)
|
os.unlink() 行为与 os.remove() 一致,函数无返回,如果文件不存在,报错 FileNotFoundError。
9.3.1.2. 创建删除目录¶
在当前文件夹下创建单级目录使用 os.mkdir(dirname),创建多级目录使用 os.makedirs(dirpath)。
0 1 | print(os.mkdir("folder"))
print(os.makedirs("parent/folder"))
|
函数无返回,如果文件夹存在则抛出 FileExistsError 错误。
0 1 2 3 4 5 6 | import os,shutil
os.rmdir("parent/folder") # 一级目录删除
os.removedirs("parent/folder")# 递归删除
shutil.rmtree("parent") # 强制删除 parent 文件夹
shutil.rmtree("parent/folder")# 强制删除 folder 文件夹
|
与创建函数类似,以上函数均无返回值,如果删除目录不存在,不会报错。
- os.rmdir() 只删除最后一级目录 folder,并且 folder 必须为空,否则报错目录非空的 OSError。
- os.removedirs() 与 os.rmdir() 类似,文件夹必须为空,首先删除 folder,然后再删除 parent。
- shutil.rmtree() 无论目录是否非空,强制删除整个文件夹,应慎用。
9.3.1.3. 临时文件和目录¶
手动创建和删除临时文件。
0 1 2 3 4 5 6 7 8 9 10 11 | filename = '/tmp/tmp_file_%s.txt' % os.getpid()
try:
f = open(filename, 'w')
except:
pass
else:
print(f.name)
f.close()
os.remove(f.name)
>>>
/tmp/tmp_file_10973.txt
|
手动创建临时文件有几个缺点,首先需要获得一个唯一的临时文件名称,其次其他程序也可以访问该文件,这为信息安全留下隐患。
使用 tempfile 模块创建临时文件是最好的选择。其他程序无法找到或打开该文件,因为它并没有引用文件系统表,同时用这个函数创建的临时文件,关闭后会自动删除。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | import tempfile
try:
tempf = tempfile.TemporaryFile()
except:
pass
else:
print(tempf)
print(tempf.name)
tempf.close() # 关闭时自动删除
>>>
<_io.BufferedRandom name=4>
4
|
使用 tempfile 模块创建临时文件无需指定文件名。需要注意的是默认使用 w+b 权限创建文件,文本模式请使用参数 ‘w+t’ 生成临时文件。
如果需要和其他程序共享临时文件,需要生成具名的临时文件:
0 1 2 3 4 5 6 7 8 9 10 11 | try:
tempf = tempfile.NamedTemporaryFile('w+t')
except:
pass
else:
print(tempf)
print(tempf.name)
tempf.close() # 关闭时自动删除
>>>
<tempfile._TemporaryFileWrapper object at 0xb71d7a2c>
/tmp/tmpas7rymlm
|
这里使用权限 ‘w+t’ 生成的临时文件将使用文本模式读写,它在关闭后也会被自动删除。
0 1 2 3 4 5 6 | tempdir = tempfile.mkdtemp()
print(tempdir)
os.removedirs(tempdir) # 手动删除临时文件夹
>>>
/tmp/tmpffpyahtn
|
注意
tempfile.mkdtemp() 生成的临时文件夹,必须手动删除。
9.3.2. 文件和目录重命名¶
0 1 2 | try:
os.rename('fname0', 'fname1')
......
|
文件和文件夹均使用 os.rename() 方法更名,成功无返回,如果文件不存在,则报错 FileNotFoundError。
注意
当目标文件或文件夹存在时,os.rename() 不会报错,而是直接覆盖。
9.3.3. 获取文件或文件夹大小¶
os.path.getsize(fname) 返回文件大小,如果文件不存在报错 FileNotFoundError:
0 1 2 3 4 5 6 | fname = "test.txt"
# os.stat(fname).st_size ,实际上 getsize() 方法与此等价
fsize = os.path.getsize(fname)
print(fsize)
>>>
30
|
注意,如果参数指定文件夹,并不会报错,而是返回文件夹节点占用的物理存储空间大小,而不是整个文件夹内容的大小。 获取文件夹大小需要 os.walk() 遍历函数实现。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | def get_folder_size(path):
total_size = 0
for item in os.walk(path):
for file in item[2]:
try:
total_size += os.path.getsize(os.path.join(item[0], file))
except Exception as e:
print("error with file: " + os.path.join(item[0], file))
return total_size
print(get_folder_size('.'))
>>>
51171
|
9.3.4. 复制或移动文件和目录¶
9.3.4.1. 文件复制¶
shutil.copyfile(src, dst, *, follow_symlinks=True)
Copy data from src to dst.
shutile 模块的 copyfile() 方法将 src 指定的文件复制为 dst 文件,注意:
- src 和 dst 必须都是文件路径,不可以是文件夹。
- 如果 src 不存在,报错 FileNotFoundError。
- 如果 dst 文件已存在,那么会覆盖。
- follow_symlinks 为 True ,则 src 如果为软连接,则复制后 dst 也是软连接。
- 复制成功,返回新文件的路径。
0 1 2 | try:
shutil.copyfile("oldfile", "newfile")
.....
|
9.3.4.2. 目录复制¶
shutile 模块的 copytree() 方法用于复制目录,symlinks 参数指明是复制软连接还是复制文件。
copytree(srcdir, dstdir, symlinks=False, ignore=None, copy_function=<function copy2>,
ignore_dangling_symlinks=False)
Recursively copy a directory tree.
0 1 2 | try:
shutil.copytree("srcdir", "dstdir")
......
|
注意 srcdir 和 newdir 都只能是目录,且 newdir 必须不存在,否则报 FileExistsError。成功返回目标目录路径。
9.3.4.3. 移动文件和目录¶
move(src, dst, copy_function=<function copy2>)
Recursively move a file or directory to another location. This is
similar to the Unix "mv" command. Return the file or directory's
destination.
移动文件和目录均使用 shutil.move()函数,类似于 Unix 下的 mv 命令。成功返回目标文件或目录。
0 1 2 | try:
shutil.move("src", "dst")
......
|
需要注意以下几点:
- src 文件或者目录必须存在,否则报错 FileNotFoundError
- dst 如果存在并且是目录,则把 src 复制到 dst/ 下
- dst 如果不存在,则直接把 src 复制为 dst。
9.4. 文件和目录属性判定¶
有时候,我们需要判断特定路径的属性,比如是文件还是目录,如果路径不存在,这类函数不会触发异常,而是返回 False,常见判定操作如下:
判定方法 描述 os.path.isabs() 判断是否为绝对路径,以 “/” 开始的路径均为 True os.path.isfile() 判断路径是否为文件,支持软连接 os.path.isdir() 判断路径是否为目录,支持软连接 os.path.islink(path) 判断路径是否为链接 os.path.ismount(path) 判断路径是否为挂载点 os.path.exists(path) 路径存在则返回 True, 否则返回 False
以下函数,如果参数不合法,则会报相应的异常错误:
判定方法 描述 os.path.samefile(src, dst) 两个路径名是否指向同个文件后者文件夹 os.path.sameopenfile(fp1, fp2) 判断 fp1 和 fp2 文件描述符是否指向同一文件 os.path.samestat(stat1, stat2) 判断文件状态 stat1 和 stat2 是否指向同一个文件
9.5. 文件名和路径操作¶
9.5.1. 文件名和路径分割¶
下列方法不关心目录或者文件是否真实存在,它们只进行字符层面的处理,不会触发异常错误。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | abspath = os.path.abspath("tmp.txt") # 返回绝对路径
basename = os.path.basename(abspath) # 返回文件名
dirname = os.path.dirname(abspath) # 返回文件路径
print(abspath)
print(basename)
print(dirname)
print(os.path.split(abspath)) # 分割路径和文件名,返回元组类型
print(os.path.splitext(abspath)) # 分割扩展名,返回元组类型
>>>
/home/red/sdc/lbooks/ml/tmp.txt
tmp.txt
/home/red/sdc/lbooks/ml
('/home/red/sdc/lbooks/ml/tmp', '.txt')
('/home/red/sdc/lbooks/ml', 'tmp.txt')
|
还有 os.path.splitdrive(path) 方法一般用于 Windows 平台,返回驱动器名和路径组成的元组。
9.5.2. 最长路径¶
0 1 2 3 4 5 6 7 8 9 10 | path_list0 = ["/home/red/", "/home/john", "/home/lily"]
path_list1 = ["/home/VIPred/", "/home/VIPjohn", "/home/VIPlily"]
commonpath0 = os.path.commonprefix(path_list0)
commonpath1 = os.path.commonprefix(path_list1)
print(commonpath0)
print(commonpath1)
>>>
/home/
/home/VIP
|
os.path.commonprefix() 方法返回所有 path 共有的最长的路径,示例可以看出,它只是在字符层面进行匹配,它返回的不一定是路径,而只是最长匹配的字符串。
9.5.3. 路径合成¶
0 1 2 3 4 5 6 | path = os.path.join("123", "456", "tmp") #把目录和文件名合成一个路径
print(path)
>>>
123/456/tmp # Linux 平台
123\456\tmp # Windows 平台
|
os.path.join() 方法只进行字符层面的拼接,不同的平台拼接字符可能不一致,这与 '/'.join()
不同。
9.5.4. 路径转换和规范化¶
9.5.4.1. 绝对路径和相对路径¶
os.path.relpath(path, start=os.curdir) Return a relative version of a path
os.path.relpath() 方法支持设定参考路径,默认为 Python 当前工作路径。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | path = "/tmp/text.txt"
realpath = os.path.realpath(path) # 返回 path 的真实路径,将忽略任何软连接
relpath = os.path.relpath(path)
print(realpath)
print(relpath)
>>>
# Linux 平台
C:\tmp\text.txt
..\..\..\..\tmp\text.txt
# Windows 平台
/tmp/text.txt
../../../../../tmp/text.txt
|
路径相关的方法是以来于系统平台的,不同平台有不同的路径表示方法,注意区别。
9.5.4.2. 路径规范化¶
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | path = "/tmp/../text.txt"
normcase = os.path.normcase(path)
normpath = os.path.normpath(path)
print(normcase)
print(normpath)
>>>
# Linux 平台
\tmp\..\text.txt
\text.txt
# Winodws 平台
/tmp/../text.txt
/text.txt
|
- os.path.normcase(path) 通常用于路径大小写不敏感的文件系统,路径转化为小写,在Unix 和 Mac 不对路径做任何改变,Winodws 上会把 “/” 转化为 “”。
- os.path.normpath(path) 标准化路径,消除路径冗余,比如将 A//B, A/B/, A/./B and A/foo/../B 转化为 A/B。
9.6. 文件相关的时间¶
9.6.1. 时间戳分类¶
每一个文件或者目录都有记录相应操作的时间戳,通常将它们分为以下几类:
- 最后的访问时间(access time)标记为 atime。通常访问文件,比如读取时会更新访问时间。但是由于文件的时间戳是要记录在磁盘上的,如果每次访问都要写磁盘,将严重影响I/O效率,所以通常使用 relative atime 策略,也即当访问时,发现文件的 ctime 或者 mtime 比 atime 新时才更新。
- 最后的修改时间(modify time)标记为 mtime。当文件内容发生改变时更新该时间。
- 最后的更改时间(change time)标记为 ctime。Linux上,当文件内容,或者属性(所有者,操作权限,所在目录)改变时更新该时间。
- 文件的创建时间(create time)被标记为 Birth,依赖文件系统格式 Linux 上目前不支持获取该时间,在 Winodes 上它被标记为 ctime。
在 Linux 上获取时间戳的命令是 stat :
0 1 2 3 4 5 6 7 8 | # stat tmp.txt
File: ‘test.txt’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 821h/2081d Inode: 334232 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-08-02 12:08:03.475780700 +0800
Modify: 2017-08-02 12:08:03.475780700 +0800
Change: 2017-08-02 12:08:03.475780700 +0800
Birth: -
|
9.6.2. 获取时间戳¶
os.path 模块提供了三种方法来获取时间戳,其中 getctime() 在 Linux 上表示为 change time,而在 Windows 上获取的则是文件的创建时间。 这三个函数均是返回从 epoch (1970.1.1 00:00:00) 到当前时刻的秒数,浮点表示,参数也可以为路径,如果文件或目录不存在,报错 FileNotFoundError。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | fname = "test.txt"
try:
atime = os.path.getatime(fname)
mtime = os.path.getmtime(fname)
ctime = os.path.getctime(fname)
except:
pass
else:
print(atime)
print(mtime)
print(ctime)
>>>
1501646883.4757807
1501646892.1091917
1501646892.1091917
|
文件的时间戳常被用于数据同步,编译等操作。更详细的描述请参考 Unix 文件系统中的时间戳。
9.6.3. 更新访问和修改时间¶
utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)
Set the access and modified time of path.
os.utime() 方法可以更新文件或者目录的访问和修改时间,如果不提供 times 参数,则使用当前时间,否则 times 参数应该是形为 (atime, mtime) 的元组。它们是相对于 epoch 以来的秒数。
注意路径必须存在,否则报错 FileNotFoundError。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | fname = "test.txt"
try:
#os.utime(fname),更新为当前时间
os.utime(fname, (1530714880.9, 1530714592))
except:
pass
else:
print(os.path.getatime(fname))
print(os.path.getmtime(fname))
>>>
1530714880.9
1530714592.0
1543464892.8930445
|
返回指定目录下的所有文件和目录名:os.listdir()
9.7. 文件属性和权限¶
stat(path, *, dir_fd=None, follow_symlinks=True)
Perform a stat system call on the given path.
os.stat() 方法获取文件各类属性,主要包括文件权限,文件所属,链接状态,大小和时间戳。 os.path.getsize() 方法底层就是调用该方法获取文件大小的。
0 1 2 3 4 5 | print(os.stat("test.txt"))
>>>
os.stat_result(st_mode=33206, st_ino=1125899907973557, st_dev=2028413472,
st_nlink=1, st_uid=0, st_gid=0, st_size=30, st_atime=1543471075,
st_mtime=1543471075, st_ctime=1543236918)
|
修改文件权限,文件所属操作请参考 os.chmod() 和 os.chown() 手册。
9.8. 文件路径遍历¶
9.8.1. 遍历当前目录¶
os.listdir(path) 返回 path 指定的文件夹包含的文件或文件夹的名字的列表。参数必须是文件夹,否则报错 NotADirectoryError。
0 1 2 3 4 5 6 7 8 | try:
paths = os.listdir('.')
except:
pass
else:
print(paths)
>>>
['text.py', 'fileopt.py', ......]
|
9.8.2. 遍历所有子目录¶
os.walk(top, topdown=True, onerror=None, followlinks=False)
Directory tree generator.
os.walk() 中的 top 参数指定遍历文件夹, topdown 指定遍历顺序,默认从上层到子文件夹。 可以通过 os.walk() 统计文件夹大小,对每个文件进行特定处理等。
os.walk() 返回目录树迭代对象,对象成员是一个三元组,形式为 (root, dirs, files),分别对应目录,目录中文件夹和目录中文件。
0 1 2 3 4 5 6 7 8 9 10 11 12 | import os
from os.path import join, getsize
for root, dirs, files in os.walk('.'):
print(root, "consumes", end="")
print(sum([getsize(join(root, name)) for name in files]), end="")
print("bytes in", len(files), "non-directory files")
if '.git' in dirs:
dirs.remove('.git') # don't visit .git directories
>>>
. consumes 44843bytes in 31 non-directory files
./folder consumes 0bytes in 0 non-directory files
......
|
以上示例,统计每个文件夹中文件所占大小,并忽略 .git 文件夹。 os.walk() 非常适合对文件进行信息统计和批处理操作,以下是一个用于把文件夹下所有文件扩展名改为小写的函数实现:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | import os
def lower_file_extname(path):
for root, dirs, files in os.walk(path):
for i in files:
oldpath = os.path.join(root, i)
splits = os.path.splitext(oldpath)
if len(splits) != 2:
continue
newpath = splits[0] + splits[1].lower()
try:
os.rename(oldpath, newpath)
except Exception as e:
print(e)
|
9.9. 文件操作模块¶
os 模块提供一些可移植的功能函数,它们的底层依赖于操作系统。 其中 os.path 模块封装了路径相关的方法。
tempfile 模块主要提供临时文件的创建和使用。shutil 模块提供更高层的文件和目录操作方法。
其他常用的文件操作模块如下:
模块 | 描述 |
---|---|
base64 | 提供二进制字符串和文本字符串间的编码/解码操作 |
binascii | 提供二进制和 ASCII 编码的二进制字符串间的编码/解码操作 |
bz2a | 访问 BZ2 格式的压缩文件 |
csv | 访问 csv 文件(逗号分隔文件) |
filecmpb | 用于比较目录和文件 |
fileinput | 提供多个文本文件的行迭代器 |
getopt/optparsea | 提供了命令行参数的解析/处理 |
glob/fnmatch | 提供 Unix 样式的通配符匹配的功能 |
gzip/zlib | 读写 GNU zip( gzip) 文件(压缩需要 zlib 模块) |
shutil | 提供高级文件访问功能 |
c/StringIO | 对字符串对象提供类文件接口 |
tarfilea | 读写 TAR 归档文件, 支持压缩文件 |
tempfile | 创建一个临时文件(名) |
uu | 格式的编码和解码 |
zipfilec | 用于读取 ZIP 归档文件的工具 |