Fork me on GitHub

用Python读写文件

本文为译文,原文链接 read-write-files-python
本人博客: 编程禅师

使用Python做的最常见的任务是读取和写入文件。无论是写入简单的文本文件,读取复杂的服务器日志,还是分析原始的字节数据。所有这些情况都需要读取或写入文件。

在本教程中,你将学习:

  • 文件的构成以及为什么这在Python中很重要
  • Python中读取和写入文件的基础
  • 用Python进行读取和写入文件的一些情景

本教程主要面向初学者到中级的Python开发者,但是这里有一些提示,更高级的程序员也可以从中获益。

什么是文件?

在我们开始研究如何使用Python中的文件之前,了解文件究竟是什么以及现代操作系统如何处理它们的某些方面是非常重要的。

从本质上讲,文件是用于存储数据的连续字节集。这些数据以特定格式组织,可以是任何像文本文件一样简单的数据,也可以像程序可执行文件一样复杂。最后,这些字节文件被翻译成二进制文件10以便计算机更容易处理。

大多数现代文件系统上的文件由三个主要部分组成:

  1. 标题(Header):有关文件内容的元数据(文件名,大小,类型等)
  2. 数据(Data):由创建者或编辑者编写的文件内容
  3. 文件结束(EOF):表示文件结尾的特殊字符

FileForma

数据表示的内容取决于所使用的格式规范,通常由扩展名表示。例如,扩展名为.gif的文件最可能符合图形交换格式规范。有数百个(如果不是数千个)文件扩展名。对于本教程,你将只处理.txt.csv文件扩展名。

文件路径

在操作系统上访问文件时,需要文件路径。文件路径是表示文件位置的字符串。它分为三个主要部分:

  1. 文件夹路径:文件系统上的文件夹位置,后续文件夹由正斜杠/(Unix)或反斜杠\(Windows)分隔
  2. 文件名:文件的实际名称
  3. 扩展名:文件路径的末尾预先设置了句号(.),用于表示文件类型

这是一个简单的例子。假设你有一个位于文件结构中的文件,如下所示:

1
2
3
4
5
6
7
8
9
10
/

├── path/
| │
│ ├── to/
│ │ └── cats.gif
│ │
│ └── dog_breeds.txt
|
└── animals.csv

假设您要访问该cats.gif文件,并且你当前的位置与文件夹中path平级。要访问该文件,你需要浏览该path文件夹,然后查看to文件夹,最后到达该cats.gif文件。文件夹路径是path/to/。文件名是cats。文件扩展名是.gif。所以完整的道路是path/to/cats.gif

现在假设你当前的位置或当前工作目录(cwd)位于我们的示例文件夹结构的to文件夹中。可以通过文件名和扩展名简单地引用文件cats.gif,而不是引用cats.gif完整路径path/to/cats.gif

1
2
3
4
5
6
7
8
9
10
/

├── path/
| │
| ├── to/ ← Your current working directory (cwd) is here
| │ └── cats.gif ← Accessing this file
| │
| └── dog_breeds.txt
|
└── animals.csv

但对于dog_breeds.txt如何进行访问呢?如果不使用完整路径,你将如何访问?你可以使用特殊字符双点(..)来向前移动一个目录。这意味着可以在to目录使用../dog_breeds.txt引用dog_breeds.txt文件。

1
2
3
4
5
6
7
8
9
10
/

├── path/ ← Referencing this parent folder
| │
| ├── to/ ← Current working directory (cwd)
| │ └── cats.gif
| │
| └── dog_breeds.txt ← Accessing this file
|
└── animals.csv

双点(..)可以连接在一起以遍历当前目录之前的多个目录。例如,在to文件夹中要访问animals.csv,你将使用../../animals.csv

行结尾

处理文件数据时经常遇到的一个问题是新行或行结尾的表示。行结尾起源于莫尔斯电码时代,使用一个特定的符号被用来表示传输的结束或一行的结尾

后来,国际标准化组织(ISO)和美国标准协会(ASA)对电传打字机进行了标准化。ASA标准规定行尾应使用回车(序列CR\r换行(LF\n)字符(CR+LF\r\n)。然而,ISO标准允许CR+LF字符或仅LF字符。

Windows使用CR+LF字符表示新行,而Unix和较新的Mac版本仅使用LF字符。当你处理来源于不同操作系统上的文件时,这可能会导致一些复杂情况。这是一个简单的例子。假设我们检查在Windows系统上创建的文件dog_breeds.txt

1
2
3
4
5
6
7
8
9
10
Pug\r\n
Jack Russel Terrier\r\n
English Springer Spaniel\r\n
German Shepherd\r\n
Staffordshire Bull Terrier\r\n
Cavalier King Charles Spaniel\r\n
Golden Retriever\r\n
West Highland White Terrier\r\n
Boxer\r\n
Border Terrier\r\n

同样的输出将在Unix设备上以不同方式解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Pug\r
\n
Jack Russel Terrier\r
\n
English Springer Spaniel\r
\n
German Shepherd\r
\n
Staffordshire Bull Terrier\r
\n
Cavalier King Charles Spaniel\r
\n
Golden Retriever\r
\n
West Highland White Terrier\r
\n
Boxer\r
\n
Border Terrier\r
\n

这可能会使每行重复出现问题,你可能需要考虑这样的情况。

字符编码

你可能面临的另一个常见问题是字节数据的编码。编码是从字节数据到人类可读字符的转换。通常通过指定编码的格式来完成。两种最常见的编码是ASCIIUNICODE格式。ASCII只能存储128个字符,而Unicode最多可包含1,114,112个字符

ASCII实际上是Unicode(UTF-8)的子集,这意味着ASCII和Unicode共享相同的数值字符值。重要的是要注意,使用不正确的字符编码解析文件可能会导致字符转换失败和出错。例如,如果文件是使用UTF-8编码创建的,并且你尝试使用ASCII编码对其进行解析,则如果存在超出这128个值的字符,则会引发错误。


在Python中打开和关闭文件

当你想使用文件时,首先要做的就是打开它。该操作通过调用 open() 内置函数完成的。open()有一个必需的参数,它是文件的路径。open()有一个返回,是这个文件的文件对象

1
file = open('dog_breeds.txt')

打开文件后,接下来要学习的是如何关闭它。

警告:你应始终确保正确关闭打开的文件。

重要的是要记住,关闭文件是你的责任。在大多数情况下,在应用程序或脚本终止时,文件最终将被关闭。但是,无法保证实际上将会发生什么。这可能导致不必要的行为,包括资源泄漏。这也是Python(Pythonic)中的最佳实践,以确保你的代码以明确定义的方式运行并减少任何不需要的行为。

当你操作文件时,有两种方法可以确保文件正确关闭,即使遇到错误也是如此。关闭文件的第一种方法是使用try-finally块:

1
2
3
4
5
reader = open('dog_breeds.txt')
try:
# Further file processing goes here
finally:
reader.close()

如果你不熟悉try-finally块的内容,请查看Python Exceptions:An Introduction

关闭文件的第二种方法是使用以下with语句:

1
2
with open('dog_breeds.txt') as reader:
# Further file processing goes here

使用 with语句,一旦离开了with块或甚至在错误的情况下,系统也会自动关闭文件。我强烈建议你尽可能使用with语句,因为它的代码更加清晰并使你更容易处理任何意外错误。

最有可能的是,你也想要使用第二个位置参数mode。此参数是一个字符串,其中包含多个字符以表示你要如何打开文件。默认值和最常见的是'r',表示以只读模式将文件作为文本文件打开:

1
2
with open('dog_breeds.txt', 'r') as reader:
# Further file processing goes here

其他模式请看在线文档,但最常用的模式如下:

模式 含义
‘r’ 只读模式打开(默认)
‘w’ 写入模式打开,会覆盖文件
'rb''wb' 以二进制模式打开(使用字节数据读/写)

让我们回过头来谈谈文件对象。文件对象是:

“将面向文件的API(使用read()or write() 等方法)暴露给底层资源的对象。”(来源

有三种不同类型的文件对象:

  • 文本文件
  • 缓冲的二进制文件
  • 原始二进制文件

这些中每一种文件类型的都在io模块中定义。这里简要介绍了这三种类型。

文本文件

文本文件是你将遇到的最常见的文件。以下是一些如何打开这些文件的示例:

1
2
3
4
5
open('abc.txt')

open('abc.txt', 'r')

open('abc.txt', 'w')

对于此类型的文件,open()将返回一个TextIOWrapper文件对象:

1
2
3
>>> file = open('dog_breeds.txt')
>>> type(file)
<class '_io.TextIOWrapper'>

这是open()默认返回的文件对象。

缓冲二进制文件类型

缓冲二进制文件类型用于读取和写入二进制文件。以下是一些如何打开这些文件的示例:

1
2
3
open('abc.txt', 'rb')

open('abc.txt', 'wb')

对于此类型的文件,open()将返回一个BufferedReaderBufferedWriter文件对象:

1
2
3
4
5
6
>>> file  =  open ('dog_breeds.txt''rb'
>>> type (file )
<class'_io.BufferedReader'>
>>> file = open ('dog_breeds.txt''wb'
> >> type (file )
<class'_io.BufferedWriter'>

原始文件类型

原始文件类型是:

“通常用作二进制和文本流的低级构建块。”(来源

因此通常不使用它。

以下是如何打开这些文件的示例:

1
open('abc.txt', 'rb', buffering=0)

对于此类型的文件,open()将返回一个FileIO文件对象:

1
2
3
>>> file = open('dog_breeds.txt', 'rb', buffering=0)
>>> type(file)
<class '_io.FileIO'>

读写已打开的文件

打开文件后,你将需要读取或写入文件。首先,让我们来阅读一个文件。可以在文件对象上调用多种方法:

方法 描述
.read(size=-1) 这将根据size字节数从文件中读取。如果没有传递参数或None-1,那么整个文件被读取。
.readline(size=-1) 这将从该行读取最多size数量的字符。直到到行结尾,然后到下一行。如果没有参数被传递或None-1,则整行(或行剩余的部分)被读出。

使用上面使用过的 dog_breeds.txt 文件,我们来看一些如何使用这些方法的示例。以下是如何使用 .read() 命令打开和读取整个文件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> with open('dog_breeds.txt', 'r') as reader:
>>> # Read & print the entire file
>>> print(reader.read())
Pug
Jack Russel Terrier
English Springer Spaniel
German Shepherd
Staffordshire Bull Terrier
Cavalier King Charles Spaniel
Golden Retriever
West Highland White Terrier
Boxer
Border Terrier

这是一个如何使用.readline()在一行中每次读取5个字节的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> with open('dog_breeds.txt', 'r') as reader:
>>> # Read & print the first 5 characters of the line 5 times
>>> print(reader.readline(5))
>>> # Notice that line is greater than the 5 chars and continues
>>> # down the line, reading 5 chars each time until the end of the
>>> # line and then "wraps" around
>>> print(reader.readline(5))
>>> print(reader.readline(5))
>>> print(reader.readline(5))
>>> print(reader.readline(5))
Pug

Jack
Russe
l Ter
rier

译者注:第一次调用reader.readline(5) 实际打印出 Pug\r\n,因此可以看到有输出一个换行

以下是使用.readlines()将整个文件作为列表读取的示例:

1
2
3
>>> f = open('dog_breeds.txt')
>>> f.readlines() # Returns a list object
['Pug\n', 'Jack Russel Terrier\n', 'English Springer Spaniel\n', 'German Shepherd\n', 'Staffordshire Bull Terrier\n', 'Cavalier King Charles Spaniel\n', 'Golden Retriever\n', 'West Highland White Terrier\n', 'Boxer\n', 'Border Terrier\n']

上面的例子也可以通过使用list()从文件对象创建列表来完成:

1
2
3
>>> f = open('dog_breeds.txt')
>>> list(f)
['Pug\n', 'Jack Russel Terrier\n', 'English Springer Spaniel\n', 'German Shepherd\n', 'Staffordshire Bull Terrier\n', 'Cavalier King Charles Spaniel\n', 'Golden Retriever\n', 'West Highland White Terrier\n', 'Boxer\n', 'Border Terrier\n']

迭代文件中的每一行

读取文件时常见的事情是迭代每一行。以下是如何使用.readline()执行该迭代的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> with open('dog_breeds.txt', 'r') as reader:
>>> # Read and print the entire file line by line
>>> line = reader.readline()
>>> while line != '': # The EOF char is an empty string
>>> print(line, end='')
>>> line = reader.readline()
Pug
Jack Russel Terrier
English Springer Spaniel
German Shepherd
Staffordshire Bull Terrier
Cavalier King Charles Spaniel
Golden Retriever
West Highland White Terrier
Boxer
Border Terrier

迭代文件中每一行的另一种方法是使用.readlines()文件对象。请记住,.readlines()返回一个列表,其中列表中的每个元素代表文件中的一行:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> with open('dog_breeds.txt', 'r') as reader:
>>> for line in reader.readlines():
>>> print(line, end='')
Pug
Jack Russell Terrier
English Springer Spaniel
German Shepherd
Staffordshire Bull Terrier
Cavalier King Charles Spaniel
Golden Retriever
West Highland White Terrier
Boxer
Border Terrier

但是,通过迭代文件对象本身可以进一步简化上述示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> with open('dog_breeds.txt', 'r') as reader:
>>> # Read and print the entire file line by line
>>> for line in reader:
>>> print(line, end='')
Pug
Jack Russel Terrier
English Springer Spaniel
German Shepherd
Staffordshire Bull Terrier
Cavalier King Charles Spaniel
Golden Retriever
West Highland White Terrier
Boxer
Border Terrier

最后的方法更Pythonic,可以更快,更高效。因此,建议你改用它。

注意:上面的一些示例包含print('some text', end='')。这end=''是为了防止Python为正在打印的文本添加额外的换行符,并仅打印从文件中读取的内容。

现在让我们深入研究文件。与读取文件一样,文件对象有多种方法可用于写入文件:

方法 描述
.write(string) 将字符串写入文件。
.writelines(seq) 将序列写入文件。不会给每个序列项附加结尾符。这会由你来添加适当的结尾符。

以下是使用.write()和的简单示例.writelines()

1
2
3
4
5
6
7
8
9
10
11
with open('dog_breeds.txt', 'r') as reader:
# Note: readlines doesn't trim the line endings
dog_breeds = reader.readlines()

with open('dog_breeds_reversed.txt', 'w') as writer:
# Alternatively you could use
# writer.writelines(reversed(dog_breeds))

# Write the dog breeds to the file in reversed order
for breed in reversed(dog_breeds):
writer.write(breed)

使用字节

有时,你可能需要使用字节字符串处理文件。可以通过在mode参数中添加'b'字符来完成。适用于文件对象的所有相同方法。但是,每个方法都期望并返回一个bytes对象:

1
2
3
>>> with open(`dog_breeds.txt`, 'rb') as reader:
>>> print(reader.readline())
b'Pug\n'

使用b标志打开文本文件并不那么有趣。假设我们有一张Jack Russell Terrier(jack_russell.png)的可爱图片:

jack_russell.jpg

你可以在Python中打开该文件并检查内容!由于.png文件格式定义的那样,文件的标题是8个字节,如下所示:

描述
0x89 一个“魔术”数字,表示这是一个PNG的开始
0x50 0x4E 0x47 PNG 的ASCII
0x0D 0x0A DOS样式行结束 \r\n
0x1A DOS风格的EOF字符
0x0A 一个Unix风格的行结尾 \n

当打开文件并单独读取这些字节时,可以看到这确实是一个.png头文件:

1
2
3
4
5
6
7
8
9
10
11
>>> with open('jack_russell.png', 'rb') as byte_reader:
>>> print(byte_reader.read(1))
>>> print(byte_reader.read(3))
>>> print(byte_reader.read(2))
>>> print(byte_reader.read(1))
>>> print(byte_reader.read(1))
b'\x89'
b'PNG'
b'\r\n'
b'\x1a'
b'\n'

一个完整的例子: dos2unix.py

让我们把知识点整理一下,看看如何读取和写入文件的完整示例。下面是一个dos2unix类似的工具,将其转换一个文件,将它的的行结束\r\n转为\n

该工具分为三个主要部分。第一个是str2unix()将字符串从\\r\\n行结尾转换为\\n。第二个是dos2unix()将包含\r\n字符的字符串转换为\ndos2unix()调用str2unix()。最后,有__main__块,只有当文件作为脚本执行时才会调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""
A simple script and library to convert files or strings from dos like
line endings with Unix like line endings.
"""

import argparse
import os


def str2unix(input_str: str) -> str:
r"""\
Converts the string from \r\n line endings to \n

Parameters
----------
input_str
The string whose line endings will be converted

Returns
-------
The converted string
"""
r_str = input_str.replace('\r\n', '\n')
return r_str


def dos2unix(source_file: str, dest_file: str):
"""\
Coverts a file that contains Dos like line endings into Unix like

Parameters
----------
source_file
The path to the source file to be converted
dest_file
The path to the converted file for output
"""
# NOTE: Could add file existence checking and file overwriting
# protection
with open(source_file, 'r') as reader:
dos_content = reader.read()

unix_content = str2unix(dos_content)

with open(dest_file, 'w') as writer:
writer.write(unix_content)


if __name__ == "__main__":
# Create our Argument parser and set its description
parser = argparse.ArgumentParser(
description="Script that converts a DOS like file to an Unix like file",
)

# Add the arguments:
# - source_file: the source file we want to convert
# - dest_file: the destination where the output should go

# Note: the use of the argument type of argparse.FileType could
# streamline some things
parser.add_argument(
'source_file',
help='The location of the source '
)

parser.add_argument(
'--dest_file',
help='Location of dest file (default: source_file appended with `_unix`',
default=None
)

# Parse the args (argparse automatically grabs the values from
# sys.argv)
args = parser.parse_args()

s_file = args.source_file
d_file = args.dest_file

# If the destination file wasn't passed, then assume we want to
# create a new file based on the old one
if d_file is None:
file_path, file_extension = os.path.splitext(s_file)
d_file = f'{file_path}_unix{file_extension}'

dos2unix(s_file, d_file)

技巧和窍门

现在你已经掌握了读取和写入文件的基础知识,这里有一些提示和技巧可以帮助你提高技能。

__file__

__file__属性是模块的特殊属性,类似于__name__。它是:

“如果是从文件加载的,它就为加载模块的文件的路径名,”(来源

注意:__file__返回对于调用初始Python脚本的路径。如果需要完整的系统路径,可以使用os.getcwd()获取执行代码的当前工作目录。

这是一个真实的例子。在我过去的一份工作中,我对硬件设备进行了多次测试。每个测试都是使用Python脚本编写的,测试脚本文件名用作标题。然后将执行这些脚本并使用__file__特殊属性打印其状态。这是一个示例文件夹结构:

1
2
3
4
5
6
7
8
9
project/
|
├── tests/
| ├── test_commanding.py
| ├── test_power.py
| ├── test_wireHousing.py
| └── test_leds.py
|
└── main.py

运行main.py产生以下内容:

1
2
3
4
5
6
7
8
9
>>> python main.py
tests/test_commanding.py Started:
tests/test_commanding.py Passed!
tests/test_power.py Started:
tests/test_power.py Passed!
tests/test_wireHousing.py Started:
tests/test_wireHousing.py Failed!
tests/test_leds.py Started:
tests/test_leds.py Passed!

追加文件内容

有时,你可能希望追加到文件或在已有文件的末尾开始写入。这可以通过在参数mode中追加'a'字符来完成:

1
2
with open('dog_breeds.txt', 'a') as a_writer:
a_writer.write('\nBeagle')

当对dog_breeds.txt再次检查时,你将看到文件的开头未更改,Beagle现在已添加到文件的末尾:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> with open('dog_breeds.txt', 'r') as reader:
>>> print(reader.read())
Pug
Jack Russel Terrier
English Springer Spaniel
German Shepherd
Staffordshire Bull Terrier
Cavalier King Charles Spaniel
Golden Retriever
West Highland White Terrier
Boxer
Border Terrier
Beagle

同时使用两个文件

有时你可能想要读取文件并同时写入另一个文件。如果你使用在学习如何写入文件时显示的示例,它实际上可以合并到以下内容中:

1
2
3
4
5
d_path = 'dog_breeds.txt'
d_r_path = 'dog_breeds_reversed.txt'
with open(d_path, 'r') as reader, open(d_r_path, 'w') as writer:
dog_breeds = reader.readlines()
writer.writelines(reversed(dog_breeds))

创建属于你自己的上下文管理器

有时候,你可能需要通过将文件对象放在自定义类中来更好地控制文件对象。执行此操作时,除非添加一些魔术方法,否则无法再使用with语句:通过添加__enter____exit__,你将创建所谓的上下文管理器

__enter__()调用with语句时调用。__exit__()with语句块退出时被调用。

这是一个可用于制作自定义类的模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
class my_file_reader():
def __init__(self, file_path):
self.__path = file_path
self.__file_object = None

def __enter__(self):
self.__file_object = open(self.__path)
return self

def __exit__(self, type, val, tb):
self.__file_object.close()

# Additional methods implemented below

现在你已经拥有了带有上下文管理器的自定义类,你可以与使用内置open()那样使用它:

1
2
3
with my_file_reader('dog_breeds.txt') as reader:
# Perform custom class operations
pass

这是一个很好的例子。还记得我们有可爱的Jack Russell形象吗?也许你想打开其他.png文件,但不想每次都解析头文件。这是一个如何做到这一点的例子。此示例还使用自定义迭代器。如果你不熟悉它们,请查看Python迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class PngReader():
# Every .png file contains this in the header. Use it to verify
# the file is indeed a .png.
_expected_magic = b'\x89PNG\r\n\x1a\n'

def __init__(self, file_path):
# Ensure the file has the right extension
if not file_path.endswith('.png'):
raise NameError("File must be a '.png' extension")
self.__path = file_path
self.__file_object = None

def __enter__(self):
self.__file_object = open(self.__path, 'rb')

magic = self.__file_object.read(8)
if magic != self._expected_magic:
raise TypeError("The File is not a properly formatted .png file!")

return self

def __exit__(self, type, val, tb):
self.__file_object.close()

def __iter__(self):
# This and __next__() are used to create a custom iterator
# See https://dbader.org/blog/python-iterators
return self

def __next__(self):
# Read the file in "Chunks"
# See https://en.wikipedia.org/wiki/Portable_Network_Graphics#%22Chunks%22_within_the_file

initial_data = self.__file_object.read(4)

# The file hasn't been opened or reached EOF. This means we
# can't go any further so stop the iteration by raising the
# StopIteration.
if self.__file_object is None or initial_data == b'':
raise StopIteration
else:
# Each chunk has a len, type, data (based on len) and crc
# Grab these values and return them as a tuple
chunk_len = int.from_bytes(initial_data, byteorder='big')
chunk_type = self.__file_object.read(4)
chunk_data = self.__file_object.read(chunk_len)
chunk_crc = self.__file_object.read(4)
return chunk_len, chunk_type, chunk_data, chunk_crc

你现在可以打开.png文件,并使用自定义上下文管理器正确解析它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> with PngReader('jack_russell.png') as reader:
>>> for l, t, d, c in reader:
>>> print(f"{l:05}, {t}, {c}")
00013, b'IHDR', b'v\x121k'
00001, b'sRGB', b'\xae\xce\x1c\xe9'
00009, b'pHYs', b'(<]\x19'
00345, b'iTXt', b"L\xc2'Y"
16384, b'IDAT', b'i\x99\x0c('
16384, b'IDAT', b'\xb3\xfa\x9a$'
16384, b'IDAT', b'\xff\xbf\xd1\n'
16384, b'IDAT', b'\xc3\x9c\xb1}'
16384, b'IDAT', b'\xe3\x02\xba\x91'
16384, b'IDAT', b'\xa0\xa99='
16384, b'IDAT', b'\xf4\x8b.\x92'
16384, b'IDAT', b'\x17i\xfc\xde'
16384, b'IDAT', b'\x8fb\x0e\xe4'
16384, b'IDAT', b')3={'
01040, b'IDAT', b'\xd6\xb8\xc1\x9f'
00000, b'IEND', b'\xaeB`\x82'

不要重复造轮子

在处理文件时可能会遇到常见情况。大多数情况可以使用其他模块处理。您可能需要使用的两种常见文件类型是.csv.jsonReal Python已经汇总了一些关于如何处理这些内容的精彩文章:

此外,还有内置库,可以使用它们来帮助你:

  • wave:读写WAV文件(音频)
  • aifc:读写AIFF和AIFC文件(音频)
  • sunau:读取和写入Sun AU文件
  • tarfile:读取和写入tar归档文件
  • zipfile:使用ZIP存档
  • configparser:轻松创建和解析配置文件
  • xml.etree.ElementTree:创建或读取基于XML的文件
  • msilib:读取和写入Microsoft Installer文件
  • plistlib:生成并解析Mac OS X .plist文件

还有更多的东西。此外,PyPI还有更多第三方工具可用。一些流行的是以下:


总结

你现在知道如何使用Python处理文件,包括一些高级技术。使用Python中的文件现在比以往任何时候都更容易,当你开始这样做时,这是一种有益的感觉。

在本教程中,你已经了解到:

  • 什么是文件
  • 如何正确打开和关闭文件
  • 如何读写文件
  • 使用文件时的一些高级技术
  • 一些库使用常见的文件类型

qrcode_for_gh_aeefa52af384_258.jpg

关注公众号 <代码与艺术>,学习更多国外精品技术文章。

-------------本文结束感谢您的阅读-------------

本文标题:用Python读写文件

文章作者:jiangyixin

发布时间:2019年02月24日 - 11:02

最后更新:2019年02月24日 - 11:02

原始链接:http://blog.jiangyixin.top/2019/02/24/read-write-files-python/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。