16--Python 文件操作(I/O)

2019-06-18  本文已影响0人  Roger田翔
@Author : Roger TX (425144880@qq.com)
@Link : https://github.com/paotong999

Python 提供有丰富的文件 I/O 支持,Python 提供了多种方式来读取文件内容,非常简单、灵活。
使用 pathlib 和 os.path 来操作各种路径,提供全局的 open() 函数来打开文件
在 Python 的 os 模块下也包含了大量进行文件 I/O 的函数,使用这些函数来读取、写入文件也很方便

一、Python pathlib模块

pathlib 模块提供了一组面向对象的类,这些类可代表各种操作系统上的路径,程序可通过这些类操作路径。


pathlib

PurePath 和 Path 的功能和用法
关于 PurePath 和 Path 不做过多说明,如果需要,可以查看官方文档

PurePath 提供了不少属性和方法,这些属性和方法主要还是用于操作路径字符串。

from pathlib import *

pp = PurePath('abc', 'xyz', 'wawa', 'haha')    # abc\xyz\wawa\haha
# 转成Unix风格的路径
pp.as_posix()    # abc/xyz/wawa/haha

# 判断当前路径是否匹配指定模式
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

Path 还包含一个很常用的 iterdir() 方法,该方法可返回 Path 对应目录下的所有子目录和文件
Path 还包含一个 glob() 方法,用于获取 Path 对应目录及其子目录下匹配指定模式的所有文件

from pathlib import *
# 获取当前目录
p = Path('.')
# 遍历当前目录下所有文件和子目录
for x in p.iterdir():
    print(x)
# 获取上一级目录
p = Path('../')
# 获取上级目录及其所有子目录下的的py文件
for x in p.glob('**/*.py'):
    print(x)
# 获取d:/github/deeptest对应的目录
p = Path('d:/github/deeptest')
# 获取上级目录及其所有子目录下的的py文件
for x in p.glob('**/Path_test1.py'):
    print(x)

Path 读写文件

p = Path('a_test.txt')
# 以utf8字符集输出文本内容
result = p.write_text('''有一个美丽的新世界
它在远方等我
那里有天真的孩子
还有姑娘的酒窝''',  encoding='utf8')
# 返回输出的字符数
print(result)
# 指定以utf8字符集读取文本内容
content = p.read_text(encoding='utf8')
# 输出读取的文本内容
print(content)
# 读取字节内容
bb = p.read_bytes()
print(bb)

二、os.path模块常见函数

Python内置的os模块也可以直接调用操作系统提供的接口函数

import os

os.name    # 操作系统类型
os.uname()    # 详细的系统信息,Windows上不可用
os.environ    # 环境变量
os.environ.get('PATH')    # 获取某个环境变量的值
os.getcwd()    # 获取当前目录
os.chdir('../deeptest')    # 改变当前目录
os.listdir(path)    # 返回 path 对应目录下的所有文件和子目录
os.mkdir(path[, mode])    # 创建一个目录,mode代表权限,比如 0o777
os.makedirs(path[, mode])    # 创建目录以及子目录
os.rmdir(path)    # 删掉一个目录
os.rename('test.txt', 'test.py')    # 文件重命名
os.remove('test.py')    # 删除文件

os.path 模块下提供了一些操作目录的方法,这些函数可以操作系统的目录本身
提供了 exists() 函数判断该目录是否存在
提供了 getctime() 函数来获取该目录的创建时间
提供了 getmtime() 函数来获取该目录的最后一次修改时间
提供了 getatime() 函数来获取该目录的最后一次访问时间
提供了 getsize() 函数来获取指定文件的大小

os.path.abspath('.')    # 查看当前目录的绝对路径 '/Users/michael'
os.path.join('/Users/michael', 'testdir')    # 目录拼接 '/Users/michael/testdir'
os.path.split('/Users/michael/testdir/file.txt')    # 目录拆分 ('/Users/michael/testdir', 'file.txt')
os.path.splitext('/path/to/file.txt')    # 获取后缀名 ('/path/to/file', '.txt')
os.path.commonprefix(['/usr/lib', '/usr/local/lib'])    # 获取共同前缀 /usr/l
os.path.commonpath(['/usr/lib', '/usr/local/lib'])    # 获取共同路径 \usr
os.path.listdir('.')    # 获取当前路径下所有文件和目录
os.path.isfile('os.path_test.py')    # 判断是否为文件 True
os.path.isdir('os.path_test.py')    # 判断是否为目录 False

要列出当前目录下的所有目录,只需要一行代码:

[x for x in os.listdir('.') if os.path.isdir(x)]
['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]

要列出所有的.py文件,只需一行代码:

[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']

三、fnmatch模块:用于文件名的匹配

上面介绍的可以进行简单的模式匹配,但 fnmatch 模块可以支持更复杂的匹配
fnmatch 匹配支持如下通配符:

  1. *:可匹配任意个任意字符。
  2. ?:可匹配一个任意字符。
  3. [字符序列]:可匹配中括号里字符序列中的任意字符。该字符序列也支持中画线表示法。
  4. [!字符序列]:可匹配不在中括号里字符序列中的任意字符。

在该模块下提供了如下函数:

from pathlib import *
import fnmatch
# 遍历当前目录下所有文件和子目录
for file in Path('.').iterdir():
    # 访问所有以_test.py结尾的文件
    if fnmatch.fnmatch(file, '*_test.PY'):
        print(file)
names = ['a.py', 'b.py', 'c.py', 'd.py']
# 对names列表进行过滤
sub = fnmatch.filter(names, '[ac].py')
print(sub) # ['a.py', 'c.py']
print(fnmatch.translate('?.py')) # (?s:.\.py)\Z
print(fnmatch.translate('[ac].py')) # (?s:[ac]\.py)\Z
print(fnmatch.translate('[a-c].py')) # (?s:[a-c]\.py)\Z

四、open函数详解

Python 提供了一个内置的 open() 函数,传入文件名和标示符,用于打开指定文件。

f = open('/Users/michael/test.txt', 'r', True, encoding='utf8', errors='ignore')

如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容

f.read()

最后一步是调用close()方法关闭文件,文件使用完毕后必须关闭

f.close()

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。为了保证能正确地关闭文件,我们可以使用try ... finally来实现:

try:
    f = open('/path/to/file', 'r', encoding='utf8')
    print(f.read())
finally:
    if f:
        f.close()

但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:

with open('/path/to/file', 'r') as f:
    print(f.read())

文件打开模式

模式 意义
r 只读模式
w 写模式
a 追加模式
+ 读写模式,可与其他模式结合使用。比如 r+ 代表读写模式,w+ 也代表读写模式
b 二进制模式,可与其他模式结合使用。b不能使用 encodingerrors
文件打开模式

下面程序使用二进制模式来读取文本文件:

# 指定使用二进制方式读取文件内容
f = open("read_test3.py", 'rb', True)
# 直接读取全部文件,并调用bytes的decode将字节内容恢复成字符串
print(f.read().decode('utf-8'))
f.close()

在调用 open() 函数时,传入了 rb 模式,这表明采用二进制模式读取文件。此时文件对象的 read() 方法返回的是 bytes 对象,程序可调用 bytes 对象的 decode() 方法将它恢复成字符串。

上一篇 下一篇

猜你喜欢

热点阅读