Python3 - 文件和目录操作

1 文件的打开以及读写

首先通过open函数,将一个文件打开,它返回的是一个文件对象。对于文本文件,常用的打开式是 "r", "w", "a" 其中,"r"为只读方式,"w"为只写方式,并且每次打开文件时,首先清除掉这个文件的所有内容,"a"也是一种写的方式,但是是在紧接着文件内容的尾部开始写入。如果要以打开一个二进制文件,则打开方式为: "rb", "wb", "ab" (这里只以打开文本文件为例)。

在这个对象的基础之上,通过调用read等函数,对这个对象进行操作。 还有一个概念是文件操作标记,它始终指向的是下一次文件操作开始的位置。初始为0。

具体的文件操作有:

  • close() – 关闭文件。

  • read() – 一次读取文件的所有内容。

  • read(size)-一次最多读取文件的size大小(一般为字符数)的内容,并移动文件操作标记。

  • readline() – 一次读取文本文件中的一行,并移动文件操作标记。需要注意的是,readline()是遇到换行符读取停止,并读取换行符到字符串中。除此之外,还可以运用以下语句,迭代读取每一行。

    1
    2
    3
    4
    file_stream = open("path", "r")
    for line in file_stream:
    # 打印读出的每行。由于每一行最后面都带有换行符,因此需要用str.strip()方法去掉。
    print(line.strip())

  • readlines() -读取文件的所有行(用readline()读取),并返回一个list。

  • truncate(size) – 清空文件,请小心使用该命令。

  • write(stuff) – 将 stuff 写入文件。

  • tell()-返回文件操作标记的当前位置,以文件的开头为原点。

  • seek(offset) – 读写重定位

2 open函数的encoding参数

若encoding参数缺省,则默认为locale.getpreferredencoding(False)(在Mac和Linux上大多为UTF-8)。如果要读取与这个值不同的编码的文本文件,则需要指定与这个文本文件相同的编码方式给encoding参数。也即,在读取文件时,打开文件的编码方式与文件的编码方式要尽可能一致;在写入文件时,打开文件的编码方式要与所要写入文件的字符串的编码方式要尽可能一致。例如,读取GBK编码的文件:

1
f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')

注意:在Python2中,open函数是没有encoding参数的,默认用ASCII打开。比如,要打开 gbk 文件,则需要对读出的字符串进行解码,从而获得相应的 unicode 字符串。或者,可以用codecs.open()打开文件,其中可以指定打开文件的编码。

3 Universal Newlines Mode

如果 open 中的 newline 参数为 None(默认值),则表示启用 Universal Newlines Mode。在该模式下,从文件中读取的换行符都会转换为 \n;写入文件中的 \n,会根据平台的不同自动进行转换。

4 文件打开操作的另一种安全写法

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

1
2
3
4
5
6
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()

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

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

这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

对于文件写操作,也有类似的语句:

1
2
3
with open('/path/to/file', 'w') as f:
# 不会自动换行,需要手动添加\n
f.write("hello world\n")

5 运用os模块对目录和文件进行操作

Python内置的os模块中的函数由操作系统提供的接口函数实现的,因此可以直接调用os模块中的这些函数,达到对目录和文件进行操作。

5.1 查看系统信息

1
2
3
4
import os

# posix
print(os.name)

如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统。

要获取详细的系统信息,可以调用 uname()函数:

1
2
3
import os

print(os.uname())

或者 sys 模块中的 platform 方法(实质上是调用了 shell 命令 uname -s):

1
2
3
4
5
6
7
import sys

# 对于 Mac OS 会显示 darwin,对于 Ubuntu 等会显示 linux。
print(sys.platform)

# 在 Mac OS 上显示为 True。
print(sys.platform.startswith('darwin'))

5.2 查看环境变量

1
2
3
4
import os

# environ({'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'TERM_PROGRAM_VERSION': '326', 'LOGNAME': 'michael', 'USER': 'michael', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin', ...})
print(os.environ)

要获取某个环境变量的值,可以调用os.environ.get('key'):

1
2
3
4
import os

# 获取PATH的信息。
print(os.environ.get("PATH"))

5.3 文件和目录的路径的连接与拆分

  • 路径的连接

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import os

    # join第一个参数必须存在,后面可以有0个或多个参数。如果某一个参数是一个绝对路径(也即以/开头的路径),则丢弃前边已经组合的路径,从这条路径开始继续往后组合。
    # 返回的是一条合法的路径(并非一定要真实存在),在组合时会自动添加/符号,或者去掉多余的/符号。比如,前边的参数为./PythonTutorial/,后面的参数为test.py,返回的仍然是./PythonTutorial/test.py
    # 返回的是 ./PythonTutorial/test.py
    print(os.path.join("./PythonTutorial", "test.py"))

    # 返回的时 /usr/local/test.py
    print(os.path.join("./PythonTutorial/", "/usr/local/test.py"))

  • 路径的分拆

    1
    2
    3
    4
    5
    import os

    # 返回的是一个tuple,后一部分总是最后级别的目录或文件名。
    # ('/Users/jsont923/Project', 'file.txt')
    print(os.path.split('/Users/jsont923/Project/file.txt'))

  • 路径的分拆(根据最右边的.号进行分拆,第二部分为一个合法的扩展名或空)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import os

    # 从最右边的.号进行分拆,第二部分要么为一个合法的扩展名(并非一定存在),也即获得的扩展名中不能存在/等符号,要么为空。
    # ('/Users/jsont923/Project/file', '.txt')
    print(os.path.splitext("/Users/jsont923/Project/file.txt"))

    # ('/Users/jsont923/Project/PythonTutorial.txt/', '')
    print(os.path.splitext("/Users/jsont923/Project/PythonTutorial.txt/"))

    # 若路径中的某个字段中,第一个字符为.号,则这个字段肯定不是扩展名。
    # ('/Users/jsont923/Project/.PythonTutorial', '')
    print(os.path.splitext('/Users/jsont923/Project/.PythonTutorial'))

5.4 创建和删除一个目录

1
2
3
4
# 创建一个目录
os.mkdir('/Users/cuckootan/Project')
# 删除一个目录
os.rmdir('/Users/cuckootan/Project')

5.5 复制文件

os模块中是不存在复制文件的函数,原因是复制文件并非由操作系统提供的系统调用。但在shutil这个模块中提供。

1
2
3
import shutil

shutil.copyfile("sourcePath", "destPath")

5.6 重命名文件

1
2
3
import os

os.rename("sourcePath", "destPath")

5.7 删除文件

1
2
3
import os

os.remove("filePath")

5.8 列举目录中的文件(包括目录文件)

1
2
3
4
import os

# 返回path下的所有文件的文件名组成的一个list
print(os.listdir("path"))

还可以使用 glob 模块,详见官方文档。

5.9 判断一个文件是否为目录文件

1
2
3
import os

print(os.path.isdir("path"))

5.10 判断一个文件是否为普通文件

1
2
3
import os

print(os.path.isfile("path"))

Reference