文件与目录管理
前言
Python 提供了丰富的文件操作功能,用于创建、读取、写入和管理文件。以下是一些常见的文件操作及其详解:
-
打开文件:
使用内置的
open()函数来打开文件。该函数接受文件路径和打开模式作为参数,并返回一个文件对象。file = open('example.txt', 'r') # 打开 example.txt 以只读模式常见的打开模式包括:
'r':只读模式'w':写入模式(会覆盖文件内容)'a':追加模式(在文件末尾追加内容)'b':二进制模式(如'rb'、'wb')'x':排他性创建模式,如果文件已存在则抛出异常
-
读取文件内容:
使用文件对象的
read()、readline()和readlines()方法来读取文件内容。content = file.read() # 读取整个文件内容 line = file.readline() # 读取一行内容 lines = file.readlines() # 读取所有行并返回列表 -
写入文件内容:
使用文件对象的
write()方法来写入内容到文件中。with open('output.txt', 'w') as output_file: output_file.write("Hello, World!\n")使用上下文管理器 (
with语句) 可以确保在操作完成后正确关闭文件。 -
关闭文件:
使用文件对象的
close()方法来关闭文件。file.close()尽量使用
with语句来自动管理文件的打开和关闭,以避免资源泄漏。 -
迭代文件内容:
文件对象本身是可迭代的,这意味着可以使用
for循环逐行遍历文件内容。with open('example.txt', 'r') as file: for line in file: print(line) -
处理二进制文件:
通过添加
'b'到打开模式中,可以处理二进制文件。with open('binary_file', 'rb') as binary_file: data = binary_file.read() -
异常处理:
文件操作可能引发异常,如文件不存在、权限问题等。因此,最好使用异常处理来捕获和处理这些情况。
try: with open('nonexistent.txt', 'r') as file: content = file.read() except FileNotFoundError: print("File not found.")
这些是文件操作的基本知识点。在实际应用中,还可以使用更多的方法和技巧来处理文件,如处理 CSV、JSON 文件,操作目录,递归遍历文件树等。
open()
open() 函数是 Python 内置函数之一,用于打开文件并返回文件对象。可以使用该对象进行读取、写入和操作文件的操作。同时,使用 with 语句可以自动管理文件的打开和关闭,使得文件操作更加安全和简洁。
语法
- 只有
file是必选参数
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)返回值
open()函数返回一个文件对象,用于读取、写入和操作文件内容。
file
表示要打开的文件的路径字符串或文件描述符(相对路径或绝对路径)。
## 创建并写入文件
with open('example.txt', 'w') as file:
file.write("Hello, World!")
## 读取文件内容
with open('example.txt', 'r') as file:
content = file.read()
print(content)在这个示例中,open() 函数用于创建一个文件对象,然后通过 with 语句管理文件的上下文,确保文件在操作完成后被正确关闭。write() 方法用于写入内容到文件,read() 方法用于读取文件内容。
mode
mode 参数用于指定打开文件的模式,即文件的操作类型。在 open() 函数中,mode 参数是一个字符串,包含一个或多个字符,用于表示文件的访问模式和操作。不同的模式允许不同的文件操作,例如读取、写入、追加等。
以下是一些常见的 mode 参数值及其含义:
-
'r':只读模式(默认)。仅允许读取文件内容,文件必须存在,否则会引发错误。 -
'w':写入模式。仅允许写入文件内容,如果文件已经存在,会被清空;如果文件不存在,会创建新文件。 -
'a':追加模式。仅允许写入文件内容,但不会清空文件,而是在文件末尾添加数据。如果文件不存在,会创建新文件。 -
'x':独占创建模式。用于创建新文件,如果文件已存在,则引发错误。 -
't':文本模式(默认)。与其他模式一起使用,表示以文本格式打开文件(例如'rt'表示以文本只读模式打开文件)。 -
'b':二进制模式。与其他模式一起使用,表示以二进制格式打开文件(例如'rb'表示以二进制只读模式打开文件)。 -
'+':读写模式,允许读取和写入文件。不能单独使用,必须与其他模式一起使用(为r、w、a、x提供缺失的读或写能力)。'r+'、'rt+'、'r+t'只读文本模式打开,补充写能力'w+'、'wt+'、'w+t'只写文本模式打开,补充读能力,'w'能力不变
-
其他说明:
'r'、'w'、'a'、'x'为主模式,需要和't'或'b'模式配合使用,真正的默认模式为'rt'
mode 参考表
| 模式 | 是否支持读写 | 是否为缺省值 | 文件存在 | 文件不存在 | 文件指针位置 |
|---|---|---|---|---|---|
| r(read-only) | 只读 | 是 | 不报错,从头开始读 | 报错 | 0 |
| w(write) | 只写 | 否 | 文件内容将被清空 | 文件将被创建,从头写 | 0 |
| a(append) | 只写 | 否 | 追加写入 | 文件将被创建,从头写 | EOF |
| x(exists) | 只写 | 否 | 报错 | 文件将被创建,从头写 | 0 |
下面是一些示例代码,演示了不同的 mode 参数值:
## 读取文件
with open('example.txt', 'r') as file:
content = file.read()
print(content)
## 写入文件
with open('new_file.txt', 'w') as file:
file.write("Hello, New File!")
## 追加到文件
with open('existing_file.txt', 'a') as file:
file.write("\nAppending to existing file.")
## 以二进制模式读写文件
with open('binary_file.bin', 'wb+') as file:
file.write(b'Binary data')
file.seek(0)
data = file.read()
print(data)要正确使用 mode 参数,你应该根据你的需求选择适当的模式来进行文件操作。在文件打开后,使用 with 语句来确保文件在操作完成后被正确关闭。
buffering
buffering 参数用于指定文件的缓冲行为,它控制着读取或写入文件时数据如何被缓冲。
缓冲是一种将数据暂时存储在内存中,以优化文件 I/O 操作的技术。
buffering 参数有以下几种可能的取值:
-
0:不进行缓冲,数据会立即被写入文件或从文件读取。 -
1:表示行缓冲。意味着每次写入文件时会将整行数据存储在缓冲区中,直到换行符出现,然后一次性将整行数据写入文件。- 如果直到缓冲区达到上限后,依旧未出现换行符,会将数据被迫写入磁盘。
-
大于
1:表示使用固定大小的缓冲区,大小由buffering参数指定。 -
-1:默认值,使用系统默认缓冲,通常是一个较小的缓冲区。
似乎看起来很麻烦,一般来说,只需要记得:
- 文本模式,一般使用默认缓冲区大小;
- 二进制模式,是一个个字节的操作,可以指定 buffer 的大小;
- 在大多数情况下,使用默认缓冲策略是比较合适的选择;
- 一般编程中,明确知道需要写磁盘了,都会手动调一次 flush,而不是等到自动 flush 或 close 的时候。
获取系统默认的 buffering 大小:
- 一般的默认 buffer 为 4096 或 8192 字节,即 4k 或 8k 。
import io
print(io.DEFAULT_BUFFER_SIZE)
'''
8192
'''范例
下面是一些示例代码,演示了不同的 buffering 参数值:
- 无缓冲模式:
## 无缓冲模式
with open('unbuffered.txt', 'w', buffering=0) as file:
file.write('Hello, ')
file.write('World!')- 行缓冲模式:
## 行缓冲模式
with open('line_buffered.txt', 'w', buffering=1) as file:
file.write('Hello, ')
file.write('World!\n') # 换行会触发写入- 固定大小缓冲:
## 固定大小缓冲
with open('buffered.txt', 'w', buffering=4096) as file: # 使用 4KB 缓冲
file.write('Hello, ')
file.write('World!')- 默认缓冲策略:
## 默认缓冲策略
with open('default_buffered.txt', 'w') as file:
file.write('Hello, ')
file.write('World!')注意事项
报错
f = open('test', 'w+', 0)
'''
ValueError: can't have unbuffered text I/O
'''这行代码意图是打开一个名为 ’test’ 的文件,使用 ‘w+’ 模式进行操作,并且设置缓冲区大小为 0。让我们逐步解释每个部分:
-
'w+'模式:这是文件打开模式的一种,它表示以读写方式打开文件。具体来说,这会导致文件被截断(如果存在数据),然后重新写入内容。此模式下,您可以读取和写入文件。 -
0缓冲区大小:在 Python 中,文件 I/O 操作默认情况下是使用缓冲区进行的,这意味着文件中的数据将首先被读取到内存中的缓冲区,然后根据需要进行处理。缓冲区的目的是优化文件读写性能,减少频繁的物理磁盘访问。
然而,您将缓冲区大小设置为 0,这就引发了问题。根据 Python 文档,当缓冲区大小为 0 时,文件对象变成了“无缓冲”的。这就意味着每次进行读取和写入操作时,都会直接与物理磁盘进行交互,而没有任何缓冲区来优化这些操作。
这在大多数情况下都是不推荐的,因为频繁的磁盘访问可能会导致性能下降,同时也增加了对磁盘的磨损。正因为如此,Python 在这种情况下引发了一个异常。异常消息中的 “can’t have unbuffered text I/O” 意味着不能使用无缓冲的文本 I/O(输入/输出)操作。
要解决这个问题,您可以将缓冲区大小设置为一个大于 0 的值,或者干脆省略缓冲区参数,以使用默认的缓冲区大小。例如:
f = open('test', 'w+') # 使用默认的缓冲区大小或者:
f = open('test', 'w+', buffering=1024) # 使用缓冲区大小为 1024请根据您的实际需求选择合适的缓冲区大小。
不报错
f = open('test', 'w+b', 0)在这行代码中,您将文件打开模式由 'w+' 更改为 'w+b',并且仍然将缓冲区大小设置为 0。让我们逐步解释为什么这样就不会报错:
-
'w+b'模式:这是二进制读写模式。与'w+'模式类似,它允许读取和写入文件内容,但是这里的文件内容将以二进制形式进行处理。这对于处理非文本文件(如图像、音频等)非常有用。 -
0缓冲区大小:在二进制模式下,尽管您设置了缓冲区大小为 0,Python 在二进制模式下的行为会略有不同。**在二进制模式下,即使缓冲区大小设置为 0,Python 仍然会进行某种程度的缓冲,以提高性能。**这与文本模式下的无缓冲操作不同。
所以,将文件打开模式更改为 'w+b',并且将缓冲区大小设置为 0,不会引发异常,因为在二进制模式下,Python 会使用一些默认的缓冲机制,即使您明确设置缓冲区大小为 0。这使得文件的读写操作仍然在某种程度上进行缓冲,以获得更好的性能。
总之,'w+b' 模式下的缓冲机制与文本模式下的缓冲机制有所不同,因此您不会看到与您之前的代码相同的异常。
encoding
在 Python 的 open() 函数中,encoding 参数用于指定读取或写入文件时所使用的字符编码。
字符编码是一种将文本字符映射为字节序列的方式,以便在文件中存储和传输文本数据。使用正确的字符编码可以确保文件内容被正确地读取和写入,以避免字符乱码等问题。
如果不指定编码方式,默认情况下,open() 函数会使用系统默认的字符编码(例如,'utf-8'),但最好在需要时明确指定正确的字符编码,以避免问题。
常见的字符编码包括:
"utf-8":UTF-8 编码,适用于大多数文本文件,支持多种语言字符。"utf-16":UTF-16 编码,支持更多字符,但文件可能会比 UTF-8 文件大。"latin-1":ISO 8859-1 编码,适用于西欧语言字符。"ascii":ASCII 编码,仅适用于英文字符。
常见系统的默认编码:
- 在 Linux 上,常见的文本文件编码集是 UTF-8。
- Windows 中的常见文本文件编码是 cp936(也称为 GBK 或 GB2312)。
注意事项
- 二进制模式下,与编码无关
- 在读取或写入文件时,要确保使用与文件内容相匹配的字符编码。否则,可能会导致字符乱码或解码错误。
范例
以下是一些示例代码,演示了如何使用不同的 encoding 参数值:
## 使用不同的编码写入文件
with open('utf8.txt', 'w', encoding='utf-8') as file:
file.write("Hello, 你好!")
with open('latin1.txt', 'w', encoding='latin-1') as file:
file.write("Hello, world!")
## 使用不同的编码读取文件
with open('utf8.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
with open('latin1.txt', 'r', encoding='latin-1') as file:
content = file.read()
print(content)二进制模式下
- 二进制模式下,与编码无关
f = open('test', 'wb+')
print(f)
'''
<_io.BufferedRandom name='test'>
'''
f.write('啊')
'''
TypeError: a bytes-like object is required, not 'str'
'''-
f = open('test', 'wb+'):这行代码打开了一个名为 ’test’ 的文件,使用'wb+'模式,这是二进制读写模式。在此模式下,您可以读取和写入二进制数据。 -
print(f):这一行打印了文件对象f,并显示了文件的相关信息。<_io.BufferedRandom name='test'>表示这是一个带有缓冲的二进制随机访问文件。 -
f.write('啊'):这一行试图向文件写入一个字符串'啊'。然而,由于您以二进制模式打开文件,write方法期望的是一个字节序列(bytes-like object),而不是普通的字符串对象。
在 Python 3.x 中,字符串和字节序列是严格区分的。您需要将字符串转换为字节序列才能在二进制模式下写入文件。这可以通过调用字符串的 encode 方法来实现:
f.write('啊'.encode('utf-8'))在这里,我们将字符串 '啊' 编码为 UTF-8 编码的字节序列,然后将这个字节序列写入到文件中。如果您不指定编码,默认的编码通常是 UTF-8,但最好明确指定,以避免不同环境中的问题。
所以,为了在二进制模式下将字符串写入文件,您需要进行编码操作,如下所示:
with open('test', 'wb+') as f:
f.write('啊'.encode('utf-8'))errors
在 Python 的 open() 函数中,errors 参数用于指定在文件操作过程中遇到编码错误时的处理方式。当文件包含无法正确解码或编码的字符时,errors 参数可以用来控制如何处理这些错误。
在实际应用中,你可以根据需要选择适当的 errors 参数值,以便在处理文件中的编码错误时有更好的控制和适应性。
errors 参数的取值可以是以下几种:
-
"strict":默认值,表示如果出现编码错误,会引发UnicodeDecodeError(读取时)或UnicodeEncodeError(写入时)异常。 -
"ignore":忽略遇到的编码错误,直接跳过无法解码或编码的字符。 -
"replace":-
用 Unicode 替换字符(U+FFFD REPLACEMENT CHARACTER)来代替无法解码的字符(读取时)
-
或用适当的编码替换无法编码的字符(写入时)。
-
-
"backslashreplace":将无法编码的字符替换为 Unicode 转义序列,如\x,\u或\U。 -
"xmlcharrefreplace":将无法编码的字符替换为对应的 XML 实体引用。 -
"namereplace":将无法编码的字符替换为 Unicode 名称转义。
范例
下面是一些示例代码,演示了不同的 errors 参数值:
## 以不同的错误处理方式打开文件
with open('encoded_file.txt', 'r', encoding='utf-8', errors='replace') as file:
content = file.read()
print(content)
with open('write_encoded_file.txt', 'w', encoding='utf-8', errors='backslashreplace') as file:
file.write("Hello, 你好!")
with open('invalid_encoded_file.txt', 'r', encoding='utf-8', errors='ignore') as file:
content = file.read()
print(content)newline
newline 参数用于控制文本文件在读取和写入时的换行符处理方式。
常用的取值为 None()、''(不进行换行转换)、'\n'(强制使用换行符 `\n’)等。
newline 参数在处理不同操作系统间的文本文件换行符问题时非常有用。它使你能够在文件读写时更好地控制换行符的行为。
newline 参数可以接受以下几种值:
-
None(默认值):使用系统默认换行模式,这意味着换行符的处理由系统自动决定。-
在读取文本时,会将所有不同的换行符表示都转换为
'\n'。 -
在写入文本时,会将
'\n'换行符转换为适当的系统换行符表示。
-
-
''(空字符串):这会禁用换行符的自动转换。-
在读取时,换行符将被视为普通字符。
-
在写入时,
'\n'换行符不会被自动转换,而会按照原样写入。
-
-
其他字符串:你可以提供自定义的换行符表示,例如
' '(空格),'\r\n'(Windows 风格),'\r'(老式 Mac 风格)等。-
在读取时,会将所有的自定义换行符表示转换为
'\n'。 -
在写入时,会将
'\n'换行符转换为你指定的自定义换行符表示。
-
不同操作系统的默认换行符:
- Windows:
'\r\n' - Unix/Linux:
'\n' - Mac:
'\r'
范例
下面是一些示例代码,演示了不同的 newline 参数值:
## 使用不同的 newline 参数值
with open('newlines.txt', 'w', newline='') as file:
file.write('Line 1\nLine 2\nLine 3\n')
with open('read_newlines.txt', 'r', newline='') as file:
content = file.read()
print(content) # 换行符保留原样
with open('custom_newlines.txt', 'w', newline='\r\n') as file:
file.write('Line 1\nLine 2\nLine 3\n')
with open('read_custom_newlines.txt', 'r', newline='\r\n') as file:
content = file.read()
print(content) # 换行符被转换为 '\n'closefd
closefd 参数用于控制是否在文件关闭时同时关闭文件描述符。
在大多数情况下,使用默认的 closefd=True 是更常见和推荐的做法,因为它符合通常的文件操作模式,并在关闭文件时处理相关资源的清理工作。
closefd 参数可以有以下两种取值:
-
True(默认值):当文件被关闭时,同时也会关闭与该文件关联的文件描述符。这是默认行为,与普通的文件操作一致。 -
False:当文件被关闭时,不会关闭与该文件关联的文件描述符。这在某些情况下可能会有用,例如当你想在关闭 Python 文件对象时保留底层文件描述符的控制权,以便在后续的操作中继续使用它。
文件描述符:
- 文件描述符是一个用于跟踪打开文件的整数值,它在操作系统层面用于管理文件。
范例
下面是一个示例代码,演示了不同的 closefd 参数值:
import os
## 使用 closefd=True,文件关闭时同时关闭文件描述符
with open('closefd_example.txt', 'w', closefd=True) as file:
file.write('Hello, World!')
## 使用 closefd=False,文件关闭时不关闭文件描述符
fd = os.open('closefd_example.txt', os.O_WRONLY)
with open(fd, 'w', closefd=False) as file:
file.write('Hello again!')
os.close(fd) # 需要手动关闭文件描述符
## 验证文件内容
with open('closefd_example.txt', 'r') as file:
content = file.read()
print(content)opener
一个可调用对象,用于在打开文件时自定义底层的文件打开行为。
在 Python 中,opener 参数通常与内置的 open() 函数一起使用,用于自定义文件打开的行为。opener 参数应该是一个可调用对象(函数),它会在每次打开文件时被调用,允许你自定义文件的打开方式和返回的文件对象。
通常,你可以使用 opener 参数来实现特定的文件打开逻辑,例如处理特殊文件格式、加密/解密等。下面是一个简单的示例:
class CustomOpener:
def __init__(self, base_opener):
self.base_opener = base_opener
def __call__(self, filename, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True):
if filename.endswith('.custom'):
# 如果文件名以 '.custom' 结尾,则进行特定处理
print("Opening custom file:", filename)
return self.custom_open(filename, mode, buffering, encoding, errors, newline, closefd)
else:
# 否则,使用默认的文件打开方式
return self.base_opener(filename, mode, buffering, encoding, errors, newline, closefd)
def custom_open(self, filename, mode, buffering, encoding, errors, newline, closefd):
# 自定义的文件打开逻辑,这里简单地返回一个假的文件对象
return FakeFile(filename, mode)
class FakeFile:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def write(self, text):
print(f"Writing to {self.filename}: {text}")
def close(self):
print(f"Closing {self.filename}")
## 创建一个自定义的 opener
custom_opener = CustomOpener(open)
## 使用自定义的 opener 打开文件
with custom_opener('example.custom', 'w') as file:
file.write("Hello, Custom!")
with custom_opener('regular.txt', 'w') as file:
file.write("Hello, Regular!")在这个示例中,CustomOpener 类继承了 open() 函数的默认行为,但在文件名以 .custom 结尾时会进行特殊处理。这个自定义的 opener 允许你在打开文件时执行额外的逻辑,比如实现特定格式的文件处理或者记录打开和关闭操作。请注意,这只是一个简单的示例,实际应用中的 opener 可能会更复杂。
需要注意的是,opener 参数在 Python 3.3 之后的版本中已经不推荐使用,而且在 Python 3.9 中已经被标记为废弃。更好的做法是使用上下文管理器(with 语句)来处理文件的打开和关闭操作。
with 语句
with 语句是 Python 中的一个上下文管理器,用于在执行一系列代码块之前和之后执行一些特定的操作。在文件操作中,with 语句通常用来打开文件并在操作结束后自动关闭文件,从而避免了忘记手动关闭文件或出现异常时没有正确关闭文件的问题。
上下文管理器和with语句提供了一种优雅的方式来管理资源,如文件、网络连接等,在进入和退出上下文时自动执行初始化和清理操作,避免了常见的错误和资源泄漏问题。
with 语句的基本语法如下:
with open('filename', 'mode') as file:
# 在此处执行文件操作
# 文件会在退出这个代码块后自动关闭在这个语法中,open('filename', 'mode') 会返回一个文件对象,该文件对象会在进入 with 代码块时被创建,并在退出代码块时自动关闭。
例子1:
以下是一个使用 with 语句进行文件读写的示例:
## 使用 with 语句读取文件
with open('example.txt', 'r') as file:
content = file.read()
print(content)
## 使用 with 语句写入文件
with open('new_file.txt', 'w') as file:
file.write("Hello, New File!")
## 使用 with 语句追加到文件
with open('existing_file.txt', 'a') as file:
file.write("\nAppending to existing file.")with 语句确保在进入和退出代码块时文件会被正确打开和关闭,这样可以提高代码的可读性和可维护性,并降低出错的可能性。同时,它也适用于其他需要上下文管理的场景,例如数据库连接、网络操作等。
例子2:
## pwd
/root/python
## cat config.json
{
"host": "10.0.0.123",
"password": "123456",
"database": "test",
"user": "azheng",
"port": 3306:
}
## cat test_os.py
#!/usr/local/bin/python3
import os
with open(os.path.join(os.path.dirname(__file__), 'config.json')) as f:
print(f.read())
## ./test_os.py
{
"host": "10.0.0.123",
"password": "123456",
"database": "test",
"user": "azheng",
"port": 3306:
}其他说明
上下文管理:
- 使用 with 关键字,上下文管理针对的是 with 后的对象;
with关键字用于创建一个上下文管理器,该上下文管理器负责管理指定的对象的上下文环境。在进入with代码块时,会自动为对象建立上下文,执行所需的初始化操作;而在退出with代码块时,会自动执行清理操作。
- 可以使用 as 关键字,as 后面其实是对象的标识符;
as关键字后面的标识符将引用在with语句中指定的对象。这个标识符可以在with代码块中使用,用于引用被管理的对象。
- 上下文管理的语句块并不会开启新的作用域。
- 与一般的代码块不同,
with语句块内部并不会创建一个新的作用域。这意味着在with块中定义的变量或对象在块外部仍然可见和访问。
- 与一般的代码块不同,
文件对象上下文管理:
- 进入 with 时,with 后的文件对象是被管理的对象;
- 在文件操作的情境下,
with后的文件对象是被上下文管理的对象。这意味着在进入with块时,文件对象会被初始化以及配置,而在退出with块时,会自动关闭文件对象。
- 在文件操作的情境下,
- as 子句后的标识符,指向 with 后的文件对象;
as后面的标识符引用了被上下文管理的对象,也就是在with语句中指定的文件对象。你可以使用这个标识符在with代码块中操作和引用文件对象。
- with 语句块执行完的时候,会自动关闭文件对象。
- 在文件操作的情况下,
with语句块执行完毕时会自动关闭文件对象,无需手动调用文件的关闭方法。这有助于确保文件资源被正确释放,避免资源泄漏问题。
- 在文件操作的情况下,
第一种写法:
with open('test') as f:
print(f, f.closed)
f.write("abc") # 文件只读,写入失败
## 测试f是否关闭
print(f.closed) # f 的作用域第二种写法:
f1 = open('test')
print(f1.closed)
with f1:
f1.write("abc") # 文件只读,写入失败
## 测试f是否关闭
print(f.closed) # f 的作用域示例
mode
- 此处
test文件定义的是相对路径,因此test文件要在当前目录中存在
r
f = open('test')
print(f)
'''
<_io.TextIOWrapper name='test' mode='r' encoding='cp936'>
'''
print(f.readable())
'''
True
'''
print(f.writable())
'''
False
'''
print(f.read())
'''
'''
print(f.write('abc'))
'''
io.UnsupportedOperation: not writable
'''
f.close()w
f = open('test')
print(f)
'''
<_io.TextIOWrapper name='test' mode='w' encoding='cp936'>
'''
print(f.readable())
'''
False
'''
print(f.writable())
'''
True
'''
print(f.write('abc'))
'''
3 # 返回值为写入的字符数。如果为b模式,则返回的是写入的字节数。
'''
print(f.read())
'''
io.UnsupportedOperation: not readable # 只能写,不能读
'''
f.close()a
x
b
t
+
111
f = open('test', 'r+')
print(f.write('abcd'))
'''
4 # 写入了四个字符
'''
f.close()
f = open('test')
print(f.read(3))
'''
abc
'''
print(f.read(1))
'''
d
'''
print(f.read(1))示例
在下面的示例中,展示了使用 open() 函数进行文件读写操作的几种常见用法。
## 读取文件
with open('file.txt', 'r') as file:
content = file.read()
print(content)- 首先通过
open('file.txt', 'r')打开一个名为'file.txt'的文件,并以只读模式打开。通过调用file.read()读取文件的内容,并将结果赋给变量content。然后打印出文件的内容。
## 写入文件
with open('file.txt', 'w') as file:
file.write('Hello, World!')- 接下来通过
open('file.txt', 'w')打开同一个文件,并以写入模式打开。通过调用file.write()将字符串'Hello, World!'写入文件。
## 追加文件
with open('file.txt', 'a') as file:
file.write(' OpenAI')- 然后通过
open('file.txt', 'a')打开同一个文件,并以追加模式打开。通过调用file.write()将字符串' OpenAI'追加到文件末尾。
## 按行读取文件
with open('file.txt', 'r') as file:
for line in file:
print(line)- 通过
open('file.txt', 'r')再次打开同一个文件,并以只读模式打开。通过使用for循环和迭代文件对象,按行读取文件内容,并逐行打印。
## 使用指定编码打开文件
with open('file.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)- 最后通过
open('file.txt', 'r', encoding='utf-8')打开文件,并指定编码方式为'utf-8'。这样可以确保以指定编码方式读取文件的内容。
read()
read() 是文件对象的方法之一,在Python中用于从打开的文件中读取内容。
语法:
content = file_object.read(size)参数:
size(可选):要读取的字节数。如果不指定,将会读取整个文件内容。如果指定了大小,将会读取指定字节数的内容。
返回值:
read()方法返回从文件中读取的内容,作为一个字符串。
注意事项:
- 每次调用
read()会从上次读取结束的位置继续读取,直到文件结尾。如果你再次调用read(),将会返回剩余的内容,而不是从文件开头开始读取。 - 如果在不指定大小的情况下使用
read(),它将会读取整个文件内容,直到文件结束。如果文件非常大,可能会一次性读取到内存中,因此在处理大文件时要小心内存消耗。
示例:
## 以读取模式打开文件,并读取整个文件内容
with open('example.txt', 'r', encoding='utf-8') as file_object:
content = file_object.read()
print(content)## 以读取模式打开文件,并读取前10个字节的内容
with open('example.txt', 'r', encoding='utf-8') as file_object:
partial_content = file_object.read(10)
print(partial_content)readline()
readline() 是文件对象的方法之一,在Python中用于从文件中读取一行内容。
readline() 方法是文件对象在逐行读取文件内容时常用的方法之一。
语法:
line = file_object.readline()参数:
readline()方法没有参数。
返回值:
readline()方法返回文件中的一行内容,作为一个字符串。如果文件已经到达结尾,那么返回一个空字符串。
注意事项:
- 每次调用
readline()方法会从文件中读取一行内容,包括行末的换行符(\n)。如果你希望去除行末的换行符,可以使用.strip()方法。 - 需要注意的是,如果文件很大,连续使用多次
readline()可能会导致内存消耗较大。在处理大文件时,你可能需要考虑逐块读取文件内容,而不是逐行读取。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
line1 = file_object.readline()
line2 = file_object.readline()
print("Line 1:", line1)
print("Line 2:", line2)在示例中,如果 example.txt 包含以下内容:
Hello, World!
This is a sample file.
上述代码会输出:
Line 1: Hello, World!
Line 2: This is a sample file.
readlines()
readlines() 是文件对象的方法之一,在Python中用于从文件中读取所有行,并将每一行作为一个字符串存储在一个列表中。
readlines() 方法在逐行处理文件内容时是一个有用的工具,特别适合读取文本文件中的多行内容。
语法:
lines_list = file_object.readlines()参数:
readlines()方法没有参数。
返回值:
readlines()方法返回一个包含文件中所有行内容的列表,其中每个元素都是一个字符串,对应文件的一行。
注意事项:
readlines()方法将文件的每一行都读取到一个列表中,你可以遍历这个列表来处理每一行的内容。需要注意的是,列表中的每个元素都包含行末的换行符,如果希望去除换行符,可以使用.strip()方法。- 与
readline()方法不同,readlines()一次性将整个文件的内容读取到内存中,因此在处理大文件时需要注意内存消耗。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
lines = file_object.readlines()
for line in lines:
print(line.strip()) # 去除行末的换行符在示例中,如果 example.txt 包含以下内容:
Hello, World!
This is a sample file.
上述代码会输出:
Hello, World!
This is a sample file.
write()
write() 是文件对象的方法之一,在Python中用于向文件中写入内容。
在使用 write() 方法写入内容时,如果文件不存在,Python会自动创建这个文件。如果文件已经存在,write() 方法会将指定的内容写入文件中,覆盖原有内容。如果你希望在文件末尾追加内容而不覆盖原有内容,可以在打开文件时使用追加模式 'a'。
总之,write() 方法是文件对象在写入文件内容时常用的方法之一。
语法:
file_object.write(content)参数:
content:要写入文件的内容,通常是一个字符串。
返回值:
write()方法没有返回值,但它会将指定的内容写入文件。
注意事项:
write()方法写入的内容必须是字符串。如果需要将其他数据类型写入文件,需要先将其转换为字符串形式。
示例:
## 以写入模式打开文件,并向文件中写入内容
with open('output.txt', 'w', encoding='utf-8') as file_object:
file_object.write('Hello, world!')## 以写入模式打开文件,并追加内容到文件末尾
with open('output.txt', 'a', encoding='utf-8') as file_object:
file_object.write('\nAppended content.')writelines()
writelines() 是文件对象的方法之一,在Python中用于向文件中写入多行内容。
通常,writelines() 方法用于将多行文本一次性写入文件,特别适合写入批量数据、日志等情况。
语法:
file_object.writelines(lines)参数:
lines:一个包含多个字符串的列表,每个字符串表示一行要写入的内容。
返回值:
writelines()方法没有返回值,它会将列表中的每个字符串写入文件。
注意事项:
writelines()方法不会自动添加换行符,因此如果希望每行之间有换行,需要在每个字符串的末尾添加\n。
示例:
lines = ['Line 1\n', 'Line 2\n', 'Line 3\n']
with open('output.txt', 'w', encoding='utf-8') as file_object:
file_object.writelines(lines)在示例中,writelines() 方法将列表中的每个字符串写入文件中,形成多行内容。每个字符串都代表文件中的一行,\n 表示换行符。
close()
close() 是文件对象的方法之一,在Python中用于关闭已打开的文件。
语法:
file_object.close()参数:
close()方法没有参数。
返回值:
close()方法没有返回值,它只是将文件对象关闭。
示例:
file_object = open('example.txt', 'r', encoding='utf-8')
content = file_object.read()
file_object.close() # 关闭文件对象with open('output.txt', 'a', encoding='utf-8') as file_object:
file_object.write('New content')
## 文件会在 with 代码块结束后自动关闭在打开文件后,通常应该在不需要继续操作文件时调用 close() 方法来关闭文件。这样可以释放文件资源,避免文件被占用而无法被其他程序使用。
然而,更好的做法是使用 with 语句,它会在代码块结束时自动关闭文件,不需要显式调用 close() 方法。这可以确保文件被正确关闭,避免因为忘记关闭文件而导致的问题。
seek()
seek() 是文件对象的方法之一,在Python中用于移动文件指针的位置,从而改变文件读取或写入的位置。
seek() 方法在处理文件时非常有用,可以控制文件指针的位置,从而在文件中定位到需要的位置进行读取或写入操作。
语法:
file_object.seek(offset, whence)参数:
offset:要移动的偏移量,可以为正数或负数。正数表示向后移动,负数表示向前移动。whence:指定偏移量的参考位置,可以是以下值之一:0:从文件开头开始计算偏移量(默认值)。1:从当前文件指针位置开始计算偏移量。2:从文件末尾开始计算偏移量。
返回值:
seek()方法没有返回值,它会将文件指针移动到指定位置。
常见用法:
seek(0),seek(0, 0)移动指针到文件开头seek(0, 2)移动指针到文件结尾
示例1:
with open('example.txt', 'r', encoding='utf-8') as file_object:
content = file_object.read(10) # 读取前10个字节
print(content)
# 移动指针到文件开头
file_object.seek(0, 0)
content = file_object.read(10) # 再次读取前10个字节
print(content)在示例中,首先使用 read(10) 读取了文件的前10个字节。然后使用 seek(0, 0) 将文件指针移动到文件开头,然后再次使用 read(10) 读取了文件的前10个字节。这次读取结果将会和之前的结果一样,因为文件指针被重新定位到了开头。
示例2:
## cat test_simplejson.py
#!/usr/local/bin/python3
import os
import simplejson
with open(os.path.join(os.path.dirname(__file__), 'config.json')) as f:
print(f.read())
print(simplejson.load(f))
root@local-test:~/python# ./test_simplejson.py
{
"host": "10.0.0.123",
"password": "123456",
"database": "test",
"user": "azheng",
"port": 3306
}
Traceback (most recent call last):
File "/root/python/./test_simplejson.py", line 7, in <module>
print(simplejson.load(f))
File "/usr/local/lib/python3.10/site-packages/simplejson/__init__.py", line 452, in load
return loads(fp.read(),
File "/usr/local/lib/python3.10/site-packages/simplejson/__init__.py", line 514, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python3.10/site-packages/simplejson/decoder.py", line 386, in decode
obj, end = self.raw_decode(s)
File "/usr/local/lib/python3.10/site-packages/simplejson/decoder.py", line 416, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)问题出现在你尝试两次读取文件 config.json。第一次你使用了 f.read() 来读取文件内容,然后再尝试使用 simplejson.load(f) 来读取同一个文件对象。由于文件对象已经在第一次读取后到达了文件末尾,因此第二次读取将无法成功。
解决方法是在第一次读取后重新定位文件指针到文件开头,然后再次读取文件内容。可以使用 f.seek(0) 来重新定位文件指针到文件开头,然后再调用 simplejson.load(f)。
修改代码如下所示:
import os
import simplejson
file_path = os.path.join(os.path.dirname(__file__), 'config.json')
with open(file_path) as f:
json_data = f.read()
print(json_data)
f.seek(0) # 将文件指针重新定位到文件开头
print(simplejson.load(f))这样就可以成功读取文件内容并使用 simplejson.load() 解析 JSON 数据了。
tell()
tell() 是文件对象的方法之一,在Python中用于获取文件指针的当前位置,即文件中的偏移量。
tell() 方法在需要知道文件指针位置的情况下非常有用,可以帮助你在文件中定位并控制读取或写入的位置。
语法:
position = file_object.tell()参数:
tell()方法没有参数。
返回值:
tell()方法返回一个整数,表示文件指针的当前位置(偏移量)。
注意事项:
tell()方法返回的一直都是字节的索引
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
content = file_object.read(10) # 读取前10个字节
print("Content:", content)
position = file_object.tell() # 获取当前文件指针位置
print("Position:", position)
remaining_content = file_object.read() # 继续读取剩余内容
print("Remaining content:", remaining_content)在示例中,首先使用 read(10) 读取了文件的前10个字节。然后使用 tell() 方法获取了当前文件指针的位置,即已经读取的字节数。接下来使用 read() 方法继续读取剩余的内容。
flush()
flush() 是文件对象的方法之一,在Python中用于强制将文件缓冲区中的数据写入文件。
语法:
file_object.flush()参数:
flush()方法没有参数。
返回值:
flush()方法没有返回值,它会将文件缓冲区中的数据立即写入文件。
示例:
with open('output.txt', 'w', encoding='utf-8') as file_object:
file_object.write('Hello')
file_object.flush() # 强制将缓冲区中的数据写入文件flush() 方法通常用于在文件写入之后,但还没有关闭文件的情况下,强制将缓冲区中的数据写入文件。文件对象在写入数据时,通常会将数据先写入到缓冲区中,而不是立即写入文件,这样可以提高文件写入的效率。flush() 可以用来确保缓冲区中的数据立即被写入文件,以防止数据丢失。
然而,通常情况下,在文件对象使用完毕后,会自动关闭文件并将缓冲区中的数据写入文件,因此在大多数情况下,不需要显式调用 flush() 方法。
truncate()
truncate() 是文件对象的方法之一,在Python中用于截断文件到指定大小。
truncate() 方法在文件修改时非常有用,特别是在需要控制文件大小或删除文件内容的情况下。
语法:
file_object.truncate(size=None)参数:
size(可选):指定截断后的文件大小,以字节为单位。如果不指定大小,则默认截断到当前文件指针位置。
返回值:
truncate()方法没有返回值,它会将文件截断到指定大小。
注意事项:
- 需要注意的是,
truncate()方法可以用来修改文件的大小,将文件截断为指定的大小。如果指定的大小小于当前文件大小,那么文件后面的内容将会被丢弃。如果不指定大小,默认将文件截断到当前文件指针位置。
示例:
with open('output.txt', 'r+', encoding='utf-8') as file_object:
file_object.write('Hello, World! This is a long line that will be truncated.')
file_object.truncate(15) # 截断文件到15字节大小在示例中,首先使用 write() 方法写入了一个较长的字符串到文件中。然后使用 truncate(15) 将文件截断到了指定的大小,保留前15个字节。
isatty()
isatty() 是文件对象的方法之一,在Python中用于判断文件是否为终端设备(tty)。
isatty() 方法可以在需要判断文件是否为交互式终端时使用。例如,你可以根据文件是否是终端设备来决定是否显示特定的输出或提示信息。
语法:
is_tty = file_object.isatty()参数:
isatty()方法没有参数。
返回值:
isatty()方法返回一个布尔值,表示文件是否为终端设备。如果文件是终端设备,则返回True,否则返回False。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
is_tty = file_object.isatty()
print("Is file a TTY:", is_tty)在示例中,isatty() 方法会判断打开的文件对象是否为终端设备。终端设备通常指的是交互式的终端窗口,例如命令行终端。如果文件不是终端设备,那么 isatty() 将返回 False。
readable()
readable() 是文件对象的方法之一,在Python中用于判断文件是否可读。
readable() 方法在判断文件是否能够读取时很有用,特别是在处理文件之前,可以先检查文件是否可读,避免不必要的错误。
语法:
is_readable = file_object.readable()参数:
readable()方法没有参数。
返回值:
readable()方法返回一个布尔值,表示文件是否可读。如果文件可读,则返回True,否则返回False。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
is_file_readable = file_object.readable()
print("Is file readable:", is_file_readable)在示例中,readable() 方法会判断打开的文件对象是否可读。
- 如果文件以可读模式(例如
'r'或'r+')打开,那么readable()将返回True。 - 如果文件以其他模式(例如
'w'或'a')打开,或者文件不存在,readable()将返回False。
writable()
writable() 是文件对象的方法之一,在Python中用于判断文件是否可写。
writable() 方法在判断文件是否能够写入时很有用,特别是在需要确定文件是否可以写入之前,可以使用这个方法来避免不必要的错误。
语法:
is_writable = file_object.writable()参数:
writable()方法没有参数。
返回值:
writable()方法返回一个布尔值,表示文件是否可写。如果文件以可写模式(例如'w'、'a'或'r+')打开,那么返回True,否则返回False。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
is_file_writable = file_object.writable()
print("Is file writable:", is_file_writable)- 在示例中,
writable()方法会判断打开的文件对象是否可写。- 如果文件以可写模式打开,那么
writable()将返回True。 - 如果文件以只读模式(例如
'r')打开,将返回False。
- 如果文件以可写模式打开,那么
seekable()
seekable() 是文件对象的方法之一,在Python中用于判断文件是否支持随机访问,即是否可以通过改变文件指针位置来定位读取位置。
seekable() 方法在需要根据文件是否支持随机访问来进行不同操作时很有用。通常情况下,可随机访问的文件对象允许你在文件中定位到任意位置进行读取和写入操作。
语法:
is_seekable = file_object.seekable()参数:
seekable()方法没有参数。
返回值:
seekable()方法返回一个布尔值,表示文件是否支持随机访问。如果文件支持随机访问,即可以通过改变文件指针位置来定位读取位置,那么返回True,否则返回False。
示例:
with open('example.txt', 'r', encoding='utf-8') as file_object:
is_file_seekable = file_object.seekable()
print("Is file seekable:", is_file_seekable)在示例中,seekable() 方法会判断打开的文件对象是否支持随机访问。
- 如果文件支持随机访问,那么
seekable()将返回True。 - 如果文件不支持随机访问,将返回
False,这通常发生在某些特殊类型的文件对象,如标准输入流或网络连接等。
—
文件指针
在Python中,文件指针是一个表示文件中位置的概念,它指示当前读/写操作的位置。文件指针在文件操作中非常重要,因为它决定了你将从文件中读取哪些内容或将数据写入到文件的哪个位置。
总之,文件指针是控制文件读写操作位置的重要工具。你可以根据需要在文件中移动指针,读取或写入数据,并在操作结束后适时关闭文件,以确保代码的正确性和资源管理。
打开文件:
要操作文件,首先需要使用内置的 open() 函数打开文件。此函数会返回一个文件对象,你可以使用这个对象进行读写操作。例如:
file = open("example.txt", "r") # 以只读模式打开文件文件指针位置:
当你打开文件后,文件指针初始位置通常在文件的开头,即位置0。随着读写操作的进行,文件指针会逐渐向后移动。
读取文件内容:
通过使用文件对象的 read() 方法,你可以从文件中读取一定数量的字符或字节。读取后,文件指针会移动到读取结束的位置。
content = file.read(10) # 读取前10个字符移动文件指针:
可以使用文件对象的 seek() 方法来移动文件指针到指定位置。偏移量参数可以是正数(向文件末尾移动)或负数(向文件开头移动)。
file.seek(0) # 移动到文件开头
file.seek(50, 0) # 从开头向后移动50个字节
file.seek(-20, 2) # 从文件末尾向前移动20个字节迭代文件内容:
文件对象本身也是可迭代的,可以使用 for 循环逐行读取文件内容。每次迭代后,文件指针会移动到下一行的开头。
for line in file:
print(line)写入文件内容:
使用文件对象的 write() 方法可以将数据写入文件。写入后,文件指针会移到写入结束的位置。需要注意的是,如果在写入模式下打开文件,文件原有的内容将被清空。
with open("output.txt", "w") as output_file:
output_file.write("Hello, World!")关闭文件:
操作完文件后,应该使用 close() 方法关闭文件。关闭文件会释放系统资源,并确保数据正确写入文件。
file.close()自动关闭文件:
为了避免忘记关闭文件,可以使用 with 语句,它会在代码块结束后自动关闭文件。
with open("example.txt", "r") as file:
content = file.read()
## 文件在此处自动关闭文件指针到文件末尾时,使用read()方法将读取不到文件内容
你说得对,在文件指针已经到达文件末尾时,再使用 read() 方法将无法读取到文件内容,因为已经没有更多的数据可供读取了。
当文件指针位于文件末尾时,任何进一步的读取操作都将返回空字符串(""),表示已经到达文件末尾。这是因为 read() 方法返回的是从当前位置开始往后读取的内容,而在文件末尾之后没有内容可供读取了。
为了避免这种情况,你可以在读取之前先检查文件指针的位置,然后根据需要决定是否执行读取操作。例如,可以使用 tell() 方法来获取文件指针的当前位置:
with open("example.txt", "r") as file:
content = file.read()
position = file.tell() # 获取文件指针位置
if position == len(content): # 检查指针是否在文件末尾
print("Reached end of file.")
else:
print("File content:", content)请注意,如果你想从文件的某个位置继续读取,可以使用 seek() 方法将文件指针移动到你希望的位置,然后再执行读取操作。例如:
with open("example.txt", "r") as file:
file.seek(10) # 将文件指针移动到位置10
remaining_content = file.read() # 从位置10开始读取剩余内容
print(remaining_content)总之,确保在读取文件之前检查文件指针的位置,以便在已经到达文件末尾时进行适当的处理。
类文件对象
在Python中,类文件对象是指实现了文件对象协议(File Object Protocol)的类,它们可以用于文件读写操作,以及其他与文件对象相关的操作。以下是一些常见的类文件对象:
-
内置文件对象(Built-in File Objects):Python内置了用于文件操作的文件对象,可以通过内置的
open()函数来创建。 -
文本文件对象(TextIOWrapper):这是基于文本文件的类文件对象,用于处理文本文件的读写。可以使用
open()函数以文本模式(例如:'r'、'w'、'a'等)打开文件来获取这种对象。 -
二进制文件对象(BufferedReader、BufferedWriter):用于处理二进制文件的类文件对象。与文本文件对象类似,可以使用
open()函数以二进制模式(例如:'rb'、'wb'等)打开文件来获取这些对象。 -
StringIO、BytesIO:这些是在内存中创建虚拟文件的类文件对象。
StringIO用于处理字符串数据,而BytesIO用于处理二进制数据。它们允许你将数据读写为文件对象,而无需实际创建物理文件。 -
文件迭代器(File Iterator):一些Python库(如
csv、json等)提供了自定义的类文件对象,用于读取和写入特定格式的文件。这些对象通常提供更高级别的操作,以简化与特定文件格式的交互。
这些类文件对象通常都实现了一些通用的方法,如read()、write()、close()等,使得开发者可以像操作标准文件对象一样来操作它们。你可以根据具体的需求选择适合的类文件对象来处理文件操作。
StringIO
StringIO 是 Python 中的一个类文件对象,它允许你将字符串数据读写为文件对象,而无需实际创建物理文件。这在某些情况下非常有用,比如在内存中处理文本数据。
使用 StringIO 需要导入 io 模块:
import io然后可以创建一个 StringIO 对象,对其进行读写操作,就好像操作文件一样。以下是一个简单的示例:
from io import StringIO
## 创建一个 StringIO 对象并写入数据
data = "Hello, this is some data stored in StringIO!"
string_io = StringIO()
string_io.write(data)
## 将 StringIO 指针重置到开头
string_io.seek(0)
## 从 StringIO 中读取数据
read_data = string_io.read()
print(read_data)
## 关闭 StringIO 对象
string_io.close()在这个例子中,我们创建了一个 StringIO 对象,使用 write() 方法写入数据,然后使用 seek() 方法将指针重置到开头,最后使用 read() 方法读取数据。需要注意的是,和普通的文件对象一样,我们在操作完成后应该调用 close() 方法来关闭 StringIO 对象。
StringIO 对于处理临时的文本数据,如测试数据、配置文件等,以及在不需要创建实际文件的情况下模拟文件操作,都非常有用。同样地,如果你需要处理二进制数据,可以使用 BytesIO 类似的方式。
BytesIO
BytesIO 是 Python 中的类文件对象,用于在内存中处理二进制数据,类似于 StringIO 用于处理文本数据。它允许你将二进制数据读写为文件对象,而无需实际创建物理文件。
与 StringIO 一样,使用 BytesIO 需要导入 io 模块:
import io然后可以创建一个 BytesIO 对象,对其进行读写操作,就好像操作文件一样。以下是一个示例:
from io import BytesIO
## 创建一个 BytesIO 对象并写入二进制数据
binary_data = b'\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64'
bytes_io = BytesIO()
bytes_io.write(binary_data)
## 将 BytesIO 指针重置到开头
bytes_io.seek(0)
## 从 BytesIO 中读取二进制数据
read_data = bytes_io.read()
print(read_data)
## 关闭 BytesIO 对象
bytes_io.close()在这个例子中,我们创建了一个 BytesIO 对象,使用 write() 方法写入二进制数据,然后使用 seek() 方法将指针重置到开头,最后使用 read() 方法读取数据。
BytesIO 对于处理临时的二进制数据,如图像、音频、视频等,以及在不需要创建实际文件的情况下进行二进制数据操作,都非常有用。通过在内存中操作数据,可以避免频繁的磁盘读写操作,从而提高性能和效率。同样地,如果你需要处理文本数据,可以使用 StringIO 类似的方式。
stdin
- 0
在Python中,stdin 表示标准输入,是一个类文件对象,用于接受用户的输入数据。它是 Python 的内置对象之一,可以通过 sys 模块来访问。
要使用 stdin,首先需要导入 sys 模块:
import sys然后,可以通过 sys.stdin 来获取标准输入对象,从而读取用户输入的数据。以下是一个简单的示例:
import sys
## 从标准输入中读取一行数据
input_data = sys.stdin.readline()
## 打印读取的数据
print("You entered:", input_data)在命令行中运行这个脚本时,它会等待你输入一行数据,然后将你的输入打印出来。
需要注意的是,sys.stdin 返回的是一个类文件对象,因此你可以使用类似文件对象的方法来操作它,比如 read()、readline() 等。但要注意,在交互式环境下(如Python交互式解释器或Jupyter Notebook)中,sys.stdin 并不会阻塞等待用户输入,因此你需要使用适当的方式来处理输入。
总而言之,stdin 是用于接收用户输入的标准输入对象,可以在命令行环境下或脚本中使用。
stdout
- 1
在Python中,stdout 表示标准输出,是一个类文件对象,用于将文本数据输出到屏幕或其他标准输出流。它是 Python 的内置对象之一,可以通过 sys 模块来访问。
要使用 stdout,首先需要导入 sys 模块:
import sys然后,可以通过 sys.stdout 来访问标准输出对象,从而将数据输出到屏幕。以下是一个简单的示例:
import sys
## 输出文本数据到标准输出
sys.stdout.write("Hello, this is a message to stdout\n")在命令行中运行这个脚本时,它会将消息打印到屏幕上。
通常情况下,我们可以直接使用 print() 函数来向标准输出输出数据,因为 print() 函数默认会将数据输出到 sys.stdout。例如:
print("Hello, this is a message to stdout")需要注意的是,sys.stdout 是一个类文件对象,因此你也可以使用类似文件对象的方法来操作它,比如 write()。如果你想将输出重定向到文件而不是屏幕,你可以使用标准的文件操作方法。
总而言之,stdout 是用于将文本数据输出到屏幕或其他标准输出流的标准输出对象,可以在脚本中使用。
stderr
- 2
在Python中,stderr 表示标准错误输出,是一个类文件对象,用于将错误消息和警告信息输出到屏幕或其他标准错误流。与 stdout 类似,stderr 也是 Python 的内置对象之一,可以通过 sys 模块来访问。
要使用 stderr,同样需要导入 sys 模块:
import sys然后,可以通过 sys.stderr 来访问标准错误输出对象,从而将错误消息输出到屏幕。以下是一个简单的示例:
import sys
## 输出错误消息到标准错误输出
sys.stderr.write("This is an error message\n")在命令行中运行这个脚本时,它会将错误消息打印到屏幕上。通常情况下,stderr 用于输出程序的错误信息、警告和其他重要的提示,以便程序员能够更好地理解程序的执行情况。
与 stdout 类似,你也可以使用 print() 函数来向标准错误输出输出数据,因为 print() 函数默认会将数据输出到 sys.stderr。例如:
import sys
print("This is an error message", file=sys.stderr)需要注意的是,sys.stderr 是一个类文件对象,因此你也可以使用类似文件对象的方法来操作它,比如 write()。如果你想将错误输出重定向到文件而不是屏幕,你可以使用标准的文件操作方法。
总而言之,stderr 是用于将错误消息、警告和其他重要提示输出到屏幕或其他标准错误流的标准错误输出对象,可以在脚本中使用。
—
路径操作
在Python中,处理文件路径和目录路径是非常常见的操作。Python提供了一些内置的模块来处理路径,其中最常用的是os.path模块和pathlib模块。
pathlib模块在Python 3.4及更高版本推荐使用
无论你使用哪种模块,都可以根据需要执行各种文件路径和目录路径操作。pathlib 模块在许多情况下提供了更简洁和面向对象的接口,特别是在处理路径时非常方便。
os.path
获取当前工作目录
在 Python 中,你可以使用 os.getcwd() 函数来获取当前工作目录(Current Working Directory)。当前工作目录是你当前正在运行程序的目录,文件读写操作默认会在这个目录下进行。
以下是获取当前工作目录的示例:
import os
current_dir = os.getcwd()
print("当前工作目录:", current_dir)
'''
当前工作目录: C:\Users\xiang\Desktop\files
'''运行上述代码会输出当前你的Python程序所在的目录路径。
需要注意的是,当前工作目录可以根据你运行程序的方式而变化,比如在命令行中运行、在IDE中运行或在不同的文件夹中运行。如果你需要进行文件操作,最好使用绝对路径来指定文件路径,以避免不同工作目录引起的问题。
检查路径是否存在
你可以使用 os.path.exists() 函数来检查给定的路径是否存在。这个函数会返回 True(存在)或 False(不存在)。
以下是检查路径是否存在的示例:
import os
path = "folder/subfolder/file.txt"
if os.path.exists(path):
print("路径存在:", path)
else:
print("路径不存在:", path)在上述示例中,如果路径 "folder/subfolder/file.txt" 存在,则会输出 "路径存在",否则会输出 "路径不存在"。
这个函数可以用来检查文件路径或目录路径的存在性。如果你需要判断具体是文件还是目录,可以结合使用 os.path.isfile() 和 os.path.isdir() 函数。
检查是否是文件或目录
在 Python 中,你可以使用 os.path.isfile() 和 os.path.isdir() 函数来检查一个路径是否是文件或目录。
os.path.isfile()函数用于检查给定路径是否是一个文件。os.path.isdir()函数用于检查给定路径是否是一个目录。
以下是示例代码:
import os
file_path = "folder/subfolder/file.txt"
dir_path = "folder/subfolder"
if os.path.isfile(file_path):
print("路径是一个文件:", file_path)
else:
print("路径不是一个文件:", file_path)
if os.path.isdir(dir_path):
print("路径是一个目录:", dir_path)
else:
print("路径不是一个目录:", dir_path)在上述示例中,如果 file_path 是一个文件,第一个条件会输出 "路径是一个文件",否则会输出 "路径不是一个文件"。同样,如果 dir_path 是一个目录,第二个条件会输出 "路径是一个目录",否则会输出 "路径不是一个目录"。
获取绝对路径
你可以使用 os.path.abspath() 函数来获取一个路径的绝对路径。绝对路径是从根目录开始的完整路径,可以用来表示文件或目录的确切位置。
以下是获取绝对路径的示例:
import os
relative_path = "folder/subfolder/file.txt"
absolute_path = os.path.abspath(relative_path)
print("相对路径:", relative_path) # folder/subfolder/file.txt
print("绝对路径:", absolute_path) # C:\Users\xiang\Desktop\files\folder\subfolder\file.txt在上述示例中,如果 relative_path 是相对路径,os.path.abspath() 将会返回对应的绝对路径。输出会显示相对路径和其对应的绝对路径。
__file__
- __file__ 是一个特殊属性,可以打印当前文件的路径
print(__file__)
'''
C:\Users\xiang\Desktop\files\test.py
'''拼接路径
os.path.join() 是一个用于拼接路径的函数,它可以将多个路径组合成一个有效的路径。这在构建文件路径和目录路径时非常有用,因为它会自动处理斜杠(或反斜杠)的正确分隔符,并确保路径的格式是正确的。
注意事项:
- 在不同操作系统中,路径分隔符可能不同(例如,在Windows系统中是反斜杠
\,而在Unix-like系统中是斜杠/)。使用os.path.join()可以确保生成的路径在不同系统上都能正常工作。 - join 的输入和返回值都是 string
下面是使用 os.path.join() 进行路径拼接的示例:
import os
## 以当前目录为基础,拼接文件路径
file_path = os.path.join("folder", "subfolder", "file.txt")
## 以当前目录为基础,拼接目录路径
folder_path = os.path.join("parent_folder", "child_folder")
## 拼接绝对路径
absolute_path = os.path.join("C:", "Users", "username", "Documents")
print("拼接后的文件路径:", file_path)
print("拼接后的目录路径:", folder_path)
print("拼接后的绝对路径:", absolute_path)范例
import os
## 以当前目录为基础,拼接文件路径
file_path = os.path.join("/etc", "sysconfig", "a/b")
print("拼接后的文件路径:", file_path)
'''
拼接后的文件路径: /etc\sysconfig\a/b
'''获取文件名和目录名
你可以使用 os.path.basename() 函数来获取路径中的文件名(文件名包括扩展名),以及使用 os.path.dirname() 函数来获取路径中的目录名。这些函数可以帮助你从路径中提取出文件名和目录名。
以下是获取文件名和目录名的示例:
import os
file_path = "folder/subfolder/file.txt"
## 使用 os.path.basename() 获取文件名
filename = os.path.basename(file_path)
## 使用 os.path.dirname() 获取目录名
dirname = os.path.dirname(file_path)
print("文件名:", filename) # 文件名: file.txt
print("目录名:", dirname) # 目录名: folder/subfolder请注意,os.path.basename() 返回的文件名包括扩展名,而 os.path.dirname() 返回的是不包含文件名的目录路径。如果你需要获取文件名和扩展名的分离部分,可以使用 os.path.splitext() 函数,如前面的回答所示。
分割路径和扩展名
splitext
在 Python 中,使用 os.path.splitext() 函数可以分割文件路径并获取文件名和扩展名。这个函数会返回一个包含文件名和扩展名的元组。以下是使用 os.path.splitext() 的示例:
import os
file_path = "folder/subfolder/file.txt"
## 使用 os.path.splitext() 分割路径
filename, extension = os.path.splitext(file_path)
print("文件名:", filename)
'''
文件名: folder/subfolder/file
'''
print("扩展名:", extension)
'''
扩展名: .txt
'''split
- split 默认以 / 进行分割
import os
## 以当前目录为基础,拼接文件路径
file_path = os.path.join("/etc", "sysconfig", "a/b")
print("拼接后的文件路径:", file_path)
'''
拼接后的文件路径: /etc\sysconfig\a/b
'''
print("分割后的文件路径:", os.path.split(file_path))
'''
分割后的文件路径: ('/etc\\sysconfig\\a', 'b')
'''
## 通过解构的方式获取 dirname 和 basename
dirname, basename = os.path.split(file_path)
print("dirname为:", dirname)
'''
dirname为: /etc\sysconfig\a
'''
print("basename为:", basename)
'''
b
'''其他
打印父目录
from os import path
p1 = path.abspath(__file__)
print(p1)
print('#' * 30)
while p1 != path.dirname(p1):
p1 = path.dirname(p1)
print(p1)
'''
C:\python\Python3.10.11\python.exe C:\Users\xiang\Desktop\files\test.py
C:\Users\xiang\Desktop\files\test.py
##############################
C:\Users\xiang\Desktop\files
C:\Users\xiang\Desktop
C:\Users\xiang
C:\Users
C:\
'''pathlib
导入模块
from pathlib import Path这行Python代码导入了一个名为Path的类(class)从pathlib模块中。让我解释一下:
-
import关键字用于在Python中导入模块,模块是包含一组函数、类和变量的文件,它们可以在代码中被重复使用。 -
pathlib是Python标准库中的一个模块,它提供了一种用于处理文件路径和目录的面向对象的方法。这个模块使得文件和目录操作更加简洁和可读。 -
Path是pathlib模块中的一个重要类。通过创建Path对象,您可以轻松地执行文件和目录的各种操作,如创建、删除、移动、重命名、读取文件内容等。
所以,这行代码的目的是导入pathlib模块中的Path类,以便在后续的代码中使用Path类来处理文件和目录的操作。例如,您可以使用Path对象来创建文件路径、检查文件是否存在、创建目录等等。
创建 Path 对象
p1 = Path() # 当前目录,等同于Path(''), Path('.')
p2 = Path('a', 'b', 'c/d') # 当前目录下的 a/b/c/d
p3 = Path('/etc', Path('sysconfig'), 'netwrok/ifcfg') # 根下的etc目录,/etc/sysconfig/netwrok/ifcfg这段代码演示了如何使用pathlib库中的Path类来初始化不同的路径对象。让我解释一下每个路径对象的含义:
-
p1 = Path(): 这创建了一个Path对象,它代表了当前工作目录。在pathlib中,如果没有传递任何参数给Path()构造函数,它会默认表示当前目录,也就是你的Python脚本或交互式环境所运行的目录。这等同于Path('')或Path('.')。 -
p2 = Path('a', 'b', 'c/d'): 这创建了另一个Path对象,表示当前目录下的路径"a/b/c/d"。Path对象的构造函数可以接受多个参数,它们会被连接成一个完整的文件路径。在这里,参数"a"、“b”、“c/d"会被连接成一个路径,表示当前目录下的"a/b/c/d”。 -
p3 = Path('/etc', Path('sysconfig'), 'network/ifcfg'): 这创建了第三个Path对象,表示绝对路径。路径由根目录开始,依次是"/etc"、“sysconfig”、“network/ifcfg”。注意,Path('sysconfig')这部分被包装在另一个Path对象中,但它仍然是p3路径的一部分。
这些Path对象可以用于执行各种文件和目录操作,例如查找文件、创建目录、检查文件是否存在等等。使用pathlib库,您可以更方便地处理文件路径和目录,而不需要手动拼接字符串。
路径拼接
操作符 /
pathlib库中的Path对象支持通过操作符/进行路径拼接,这是因为Path类对运算符进行了重载。下面是这些运算符的用法:
Path对象 / Path对象
可以将两个Path对象相连接,创建一个新的Path对象,表示两者的组合路径。例如:
from pathlib import Path
p1 = Path('/path/to/dir')
p2 = Path('file.txt')
p3 = p1 / p2
print(p3) # 输出:/path/to/dir/file.txtPath对象 / 字符串
可以将一个字符串追加到Path对象的末尾,创建一个新的Path对象。例如:
from pathlib import Path
p1 = Path('/path/to/dir')
p2 = 'file.txt'
p3 = p1 / p2
print(p3) # 输出:/path/to/dir/file.txt字符串 / Path对象
与上述相反,可以将一个Path对象追加到字符串的末尾,创建一个新的Path对象。例如:
from pathlib import Path
p1 = '/path/to/dir'
p2 = Path('file.txt')
p3 = p1 / p2
print(p3) # 输出:/path/to/dir/file.txtjoinpath
- joinpath(*other) 在当前Path路径上连接多个字符串返回新路径对象
joinpath(*other)是pathlib库中的一个方法,用于在当前Path路径上连接多个字符串,并返回一个新的Path对象。这个方法的主要目的是用来创建新的路径,而不会修改原始的Path对象。下面是它的用法:
from pathlib import Path
## 创建一个初始的Path对象
p1 = Path('/path/to/dir')
## 使用joinpath方法连接多个字符串,创建新的Path对象
p2 = p1.joinpath('subdir', 'file.txt')
## 输出新的Path对象
print(p2) # 输出:/path/to/dir/subdir/file.txt在这个示例中,p1是初始的Path对象,然后通过调用joinpath方法连接了多个字符串'subdir'和'file.txt',从而创建了新的Path对象p2,它代表了完整的路径/path/to/dir/subdir/file.txt。原始的p1对象仍然保持不变。
from pathlib import Path
p1 = Path('/etc')
p2 = p1.joinpath('lvm', 'lvm.conf')
print(type(p1), p1) # <class 'pathlib.PosixPath'> /etc
print(type(p2), p2) # <class 'pathlib.PosixPath'> /etc/lvm/lvm.confparts 路径分解
parts属性,会返回目录各部分的元组
pathlib库的Path对象具有parts属性,它返回一个元组,其中包含了路径的各个部分。这些部分通常是目录名和文件名等路径组成部分。以下是parts属性的示例用法:
from pathlib import Path
## 创建一个Path对象表示文件路径
file_path = Path('/path/to/directory/file.txt')
## 使用parts属性获取路径的各个部分
path_parts = file_path.parts
## 输出路径的各个部分
print(path_parts)在这个示例中,parts属性会将file_path路径分解为以下元组:
('/', 'path', 'to', 'directory', 'file.txt')每个元素代表路径中的一个部分,包括根目录(如果有的话)、各级目录和最后的文件名。您可以通过索引访问元组中的特定部分,例如path_parts[0]将返回根目录,path_parts[-1]将返回文件名。这种方式使得可以轻松地获取路径中的各个组成部分,而不必手动解析字符串。
获取路径
pathlib库的Path对象提供了两种方法来获取路径的字符串表示和字节表示:
您可以根据需要选择其中的一种方法,根据您的应用程序的需求,将路径表示为字符串或字节。通常情况下,使用str()方法更为常见,因为它产生一个易于阅读和处理的普通字符串。
str() 方法
str 获取路径字符串
使用str()方法可以获取路径的字符串表示。这将返回一个普通的Python字符串,表示路径。例如:
from pathlib import Path
## 创建一个Path对象
path = Path('/path/to/file.txt')
## 获取路径的字符串表示
path_str = str(path)
## 输出路径字符串
print(path_str) # /path/to/file.txt#!/usr/local/bin/python3
from pathlib import Path
path = Path('/path/to/directory/file.txt')
path_str = str(path)
print(type(path), path) # <class 'pathlib.PosixPath'> /path/to/directory/file.txt
print(type(path_str), path_str) # <class 'str'> /path/to/directory/file.txtbytes() 方法
bytes 获取路径字符串的bytes
使用bytes()方法可以获取路径字符串的字节表示。这将返回一个字节对象,表示路径的UTF-8编码版本。例如:
from pathlib import Path
## 创建一个Path对象
path = Path('/path/to/file.txt')
## 获取路径字符串的字节表示
path_bytes = bytes(path)
## 输出路径字节表示
print(path_bytes)这将输出一个表示路径的字节对象,如 b'/path/to/file.txt'。
#!/usr/local/bin/python3
from pathlib import Path
path = Path('/path/to/directory/file.txt')
path_bytes = bytes(path)
print(type(path), path) # <class 'pathlib.PosixPath'> /path/to/directory/file.txt
print(type(path_bytes), path_bytes) # <class 'bytes'> b'/path/to/directory/file.txt'打印父目录
在pathlib库的Path对象中,有两个相关的属性,parent和parents,它们用于获取路径的父目录信息:
这些属性对于在文件系统中导航并执行路径操作非常有用,特别是在需要访问父目录或获取路径的各个部分时。
parent
目录的逻辑父目录
parent属性用于获取路径的逻辑父目录。这意味着它返回当前路径的直接上级目录,即路径中除了最后一个部分(通常是文件名)之外的部分。例如:
from pathlib import Path
## 创建一个Path对象表示文件路径
file_path = Path('/path/to/directory/file.txt')
## 获取文件路径的父目录
parent_directory = file_path.parent
## 输出父目录路径
print(parent_directory)输出将是:/path/to/directory
parent属性返回的是一个新的Path对象,表示当前路径的父目录。
#!/usr/local/bin/python3
from pathlib import Path
p1 = Path('/path/to/directory/file.txt')
p1_parent = p1.parent
print(type(p1_parent), p1_parent) # <class 'pathlib.PosixPath'> /path/to/directoryparents
父目录惰性可迭代对象,索引0是直接的父
parents属性是一个懒惰(lazy)可迭代对象,用于获取路径的所有父目录。通过对parents属性进行迭代,您可以逐级获取路径的所有父目录。索引0代表的是直接的父目录,索引1代表的是父目录的父目录,以此类推。例如:
from pathlib import Path
## 创建一个Path对象表示文件路径
file_path = Path('/path/to/directory/file.txt')
## 使用parents属性获取所有父目录
for parent in file_path.parents:
print(parent)输出将是:
/path/to/directory
/path/to
/path
/ # 根目录
parents属性返回一个可迭代对象,您可以使用for循环或转换为列表等方式来访问所有父目录。
#!/usr/local/bin/python3
from pathlib import Path
p1 = Path('/path/to/directory/file.txt')
for parent in p1.parents:
print(type(parent), parent)
'''
<class 'pathlib.PosixPath'> /path/to/directory
<class 'pathlib.PosixPath'> /path/to
<class 'pathlib.PosixPath'> /path
<class 'pathlib.PosixPath'> /
'''iterdir()
iterdir()是pathlib库中的一个方法,用于获取目录中的所有子项,包括文件和子目录。这个方法返回一个迭代器,您可以使用for循环或其他迭代方式遍历目录中的子项。
以下是使用iterdir()方法遍历目录的示例:
from pathlib import Path
## 创建一个Path对象表示目标目录
directory_path = Path('/path/to/directory')
## 使用iterdir()方法获取目录中的子项
for item in directory_path.iterdir():
print(item)在这个示例中,我们首先创建一个Path对象,表示目标目录的路径。然后,我们使用iterdir()方法获取目录中的所有子项,并通过for循环遍历它们。在循环中,item代表目录中的每个子项,它可以是文件或子目录的Path对象。
您可以根据需要对这些子项执行各种操作,例如读取文件内容、删除文件、递归处理子目录等等。iterdir()方法使得在目录中进行文件和子目录的迭代变得非常方便。
创建目录
mkdir()
mkdir()方法是pathlib库中的一个方法,用于创建目录(文件夹)。它可以用于Path对象,以在文件系统中创建新的目录。下面是mkdir()方法的用法示例:
from pathlib import Path
## 创建一个Path对象表示要创建的目录
directory_to_create = Path('/path/to/new_directory')
## 使用mkdir()方法创建目录
directory_to_create.mkdir()
## 检查目录是否创建成功
if directory_to_create.is_dir():
print(f"目录 {directory_to_create} 已成功创建。")
else:
print(f"目录 {directory_to_create} 创建失败。")在这个示例中,我们首先创建一个Path对象,表示要创建的新目录的路径。然后,我们调用mkdir()方法来创建这个目录。最后,我们使用is_dir()方法来检查目录是否已经成功创建。
需要注意的是,如果目录已经存在,调用mkdir()方法将会引发一个FileExistsError异常,因此在调用mkdir()之前,通常应该使用is_dir()方法检查目录是否已经存在,以避免重复创建。
mkdir()方法还接受一些可选参数,例如mode参数可以用于指定新目录的权限模式。如果需要更多的控制,可以查看pathlib文档以了解详细信息。
递归创建呢?
如果您想要递归地创建目录,包括所有中间目录,您可以使用mkdir()方法的parents参数。parents参数接受一个布尔值,如果将其设置为True,则会递归地创建所需的目录结构,包括所有中间目录,即使它们不存在。如果将其设置为False(默认值),则仅创建最终目录。
下面是一个示例,演示如何递归创建目录:
from pathlib import Path
## 创建一个Path对象表示要递归创建的目录
directory_to_create = Path('/path/to/new/directory/structure')
## 使用mkdir()方法递归地创建目录结构
directory_to_create.mkdir(parents=True, exist_ok=True)
## 检查目录是否已成功创建
if directory_to_create.is_dir():
print(f"目录 {directory_to_create} 及其父目录已成功创建。")
else:
print(f"目录 {directory_to_create} 创建失败。")在这个示例中,我们设置了parents=True,并且还设置了exist_ok=True,这将允许目录已存在时不引发异常。这样,mkdir()方法会递归地创建整个目录结构,包括所有中间目录。
这样,您可以确保在创建目录时递归创建整个目录结构,而不必手动创建每个中间目录。
如果目录已存在呢?
如果您使用mkdir()方法尝试创建一个目录,但该目录已经存在,它默认会引发一个FileExistsError异常。如果您想要在目录已存在时不引发异常,可以使用exist_ok=True参数。
下面是一个示例,演示如何处理目录已存在的情况:
from pathlib import Path
## 创建一个Path对象表示要创建的目录
directory_to_create = Path('/path/to/existing_directory')
try:
# 使用mkdir()方法创建目录,如果目录已存在,不引发异常
directory_to_create.mkdir(exist_ok=True)
print(f"目录 {directory_to_create} 已成功创建或已存在。")
except FileExistsError:
print(f"目录 {directory_to_create} 已经存在,未创建新目录。")在这个示例中,我们使用mkdir(exist_ok=True)来创建目录。如果目录已存在,它不会引发异常,而是简单地继续执行,这样您可以轻松处理目录已存在的情况。
如果您不使用exist_ok=True参数,并且尝试创建一个已存在的目录,那么mkdir()方法将引发FileExistsError异常。使用exist_ok=True可以避免这种异常,使代码更具健壮性。
删除目录
rmdir()
pathlib库的Path对象中有一个名为rmdir()的方法,用于删除指定的目录。这个方法只能用于删除目录,而不能删除文件。
以下是使用rmdir()方法删除目录的示例:
from pathlib import Path
## 创建一个Path对象表示要删除的目录
directory_to_delete = Path('/path/to/directory_to_delete')
## 使用rmdir()方法删除目录
try:
directory_to_delete.rmdir()
print(f"目录 {directory_to_delete} 已成功删除。")
except FileNotFoundError:
print(f"目录 {directory_to_delete} 不存在。")
except OSError as e:
print(f"无法删除目录 {directory_to_delete}: {e}")在这个示例中,我们首先创建一个Path对象,表示要删除的目录。然后,我们使用rmdir()方法尝试删除该目录。如果目录不存在,它将引发FileNotFoundError异常。如果出现其他问题(例如,目录不为空),它可能引发OSError异常。
请注意,使用rmdir()方法删除的目录必须是空目录,否则会引发异常。如果目录中包含文件或其他子目录,您需要首先删除这些文件和子目录,然后才能使用rmdir()删除父目录。如果您需要递归删除整个目录结构,可以使用shutil库中的rmtree()函数。
1
from pathlib import Path
## 创建Path对象
path = Path("folder") / "subfolder" / "file.txt"
## 获取当前工作目录
current_dir = Path.cwd()
## 获取文件名和目录名
basename = path.name
dirname = path.parent
## 检查路径是否存在
exists = path.exists()
## 检查是否是文件或目录
is_file = path.is_file()
is_dir = path.is_dir()
## 分割路径和扩展名
split_path = path.suffixes # 返回所有后缀
## 获取绝对路径
absolute_path = path.resolve()glob()
glob()是pathlib库中的一个方法,用于查找与指定通配符模式匹配的文件和目录。通配符模式是一种用于匹配文件名或路径的模式,通常包括通配符字符(例如*和?)以及目录分隔符。
以下是使用glob()方法查找文件和目录的示例:
from pathlib import Path
## 创建一个Path对象表示要搜索的目录
directory_path = Path('/path/to/directory')
## 使用glob()方法查找所有以.txt为扩展名的文件
txt_files = directory_path.glob('*.txt')
## 使用glob()方法查找所有子目录
subdirectories = directory_path.glob('*')
## 打印匹配的文件和子目录
print("匹配的.txt文件:")
for file in txt_files:
print(file)
print("\n子目录:")
for subdir in subdirectories:
if subdir.is_dir():
print(subdir)在这个示例中,我们首先创建一个Path对象,表示要搜索的目录。然后,我们使用glob()方法来查找该目录中与指定通配符模式匹配的文件和目录。在第一个例子中,我们查找所有以.txt为扩展名的文件,通配符模式是*.txt。在第二个例子中,我们查找目录中的所有子项,通配符模式是*,它匹配任何文件名或目录名。
glob()方法返回一个迭代器,您可以使用for循环或其他迭代方式遍历匹配的文件和目录。请注意,glob()方法只查找当前目录下的文件和目录,不会递归查找子目录。如果需要递归查找,可以结合使用**通配符来编写递归搜索的代码。
递归
**/*.py
如果您想使用glob()方法查找所有子目录下的.py文件,可以使用**通配符来实现递归搜索。下面是一个示例:
from pathlib import Path
## 创建一个Path对象表示要搜索的根目录
root_directory = Path('/path/to/root_directory')
## 使用glob()方法查找所有子目录中的.py文件
py_files = root_directory.glob('**/*.py')
## 打印匹配的.py文件
for file in py_files:
print(file)在这个示例中,我们首先创建一个Path对象,表示要搜索的根目录。然后,我们使用glob()方法来查找所有子目录中的.py文件。通配符模式是**/*.py,其中**表示递归查找子目录,*.py匹配所有以.py为扩展名的文件。
这将返回一个匹配的.py文件的迭代器,您可以使用for循环遍历它们。这种方式可以递归地查找所有子目录中的.py文件。
write_text()
write_text()是pathlib库中的一个方法,用于将文本内容写入文件。它可以用于Path对象,以便轻松地创建或覆盖文件的内容。
以下是使用write_text()方法将文本写入文件的示例:
from pathlib import Path
## 创建一个Path对象表示目标文件
file_path = Path('/path/to/file.txt')
## 要写入文件的文本内容
text_content = "Hello, World!\nThis is a sample text."
## 使用write_text()方法将文本写入文件
try:
file_path.write_text(text_content)
print(f"文本已成功写入文件 {file_path}.")
except Exception as e:
print(f"写入文件 {file_path} 时出现错误: {e}")在这个示例中,我们首先创建一个Path对象,表示要写入的目标文件的路径。然后,我们定义了要写入文件的文本内容,将其存储在text_content变量中。最后,我们使用write_text()方法将文本写入文件。
如果文件已经存在,write_text()方法将覆盖文件的内容。如果文件不存在,它将创建一个新文件并写入文本内容。如果在写入过程中发生任何错误,它会引发异常,因此我们使用try和except来捕获可能的异常并进行错误处理。
write_text()方法是一个方便的方法,用于将文本写入文件,而不必打开文件、写入内容,然后关闭文件。
如果想追加写入呢?
如果您想追加写入文本而不是覆盖文件的内容,您可以使用write_text()方法的mode参数并将其设置为'a'(追加模式)。这将在文件末尾添加新的文本内容而不会删除或覆盖原有的内容。
以下是追加写入文本的示例:
from pathlib import Path
## 创建一个Path对象表示目标文件
file_path = Path('/path/to/file.txt')
## 要追加到文件的文本内容
text_content_to_append = "This is additional text."
## 使用write_text()方法以追加模式将文本追加到文件
try:
file_path.write_text(text_content_to_append, mode='a')
print(f"文本已成功追加到文件 {file_path}.")
except Exception as e:
print(f"追加到文件 {file_path} 时出现错误: {e}")在这个示例中,我们仍然使用write_text()方法,但是我们将mode参数设置为'a',这表示追加模式。然后,我们提供要追加到文件的文本内容。使用追加模式时,如果文件不存在,它会创建新文件。
注意:在追加模式下,新的文本内容将被添加到文件的末尾,而不会影响原有的内容。如果您想要在文本中间的特定位置插入新内容,需要使用其他方法,如open()和文件对象的方法。
路径对象常见操作方式
from pathlib import Path
p1 = Path('/path/to/dir/file.tar.gz')
print(p1.exists) # <bound method Path.exists of WindowsPath('/path/to/dir/file.tar.gz')>
print(p1.stem) # file.tar
print(p1.suffix) # .gz
print(p1.name) # file.tar.gz(相当于 stem + suffix 拼合在一起)
print(p1.suffixes) # ['.tar', '.gz']
print(p1.with_name('config')) # \path\to\dir\config(替换基名)
print(p1.parent.parent / 'redis') # \path\to\redis
print(p1.with_suffix('.xz')) # \path\to\dir\file.tar.xz(替换扩展名)
print(p1.parent.with_suffix('.zip')) # \path\to\dir.zip(替换扩展名,只留一个扩展名)软链接
from pathlib import Path
p1 = Path('/dev')
p2 = p1 / 'cdrom'
print(p2.absolute()) # 转换为绝对路径
print(p2.resolve()) # resolve() 方法会跟踪符号链接并返回实际的文件路径。—
shutil 模块
shutil 模块是 Python 标准库中的一个模块,用于执行文件和目录操作,例如复制、移动、重命名、删除文件和目录等。它提供了一组高级文件操作功能,可以方便地管理文件系统。
导入模块
import shutil复制文件或目录
copy()
shutil.copy(src, dst): 复制文件或目录从src到dst。
shutil.copy(src, dst) 函数用于复制文件或目录从源路径 src 到目标路径 dst。这个函数将源文件或目录复制到目标位置,保持源文件的内容不变,不会更改文件的元数据(例如权限、时间戳等)。
参数:
src:要复制的源文件或目录的路径。dst:复制后的目标文件或目录的路径。
示例:
import shutil
src_file = "source_file.txt"
dst_file = "destination_file.txt"
## 复制文件
shutil.copy(src_file, dst_file)上述示例将 source_file.txt 复制到 destination_file.txt,如果目标文件已经存在,它会被覆盖。
如果您要复制一个目录,shutil.copy() 将引发 IsADirectoryError,因为它不能用于复制目录。如果要复制整个目录,可以使用 shutil.copytree() 函数。
请注意,如果您想要保留源文件的元数据(例如文件权限、时间戳等),您可以使用 shutil.copy2(src, dst) 函数,它类似于 shutil.copy(),但会保留更多元数据。
copy2()
常用
shutil.copy2(src, dst): 与copy类似,但保留源文件的元数据(如权限、时间戳等)。
shutil.copy2(src, dst) 函数用于复制文件或目录从源路径 src 到目标路径 dst,与 shutil.copy() 函数类似,但它会尽可能地保留源文件的元数据,包括文件权限、时间戳等。这使得复制后的文件在元数据方面更接近原始文件。
参数:
src:要复制的源文件或目录的路径。dst:复制后的目标文件或目录的路径。
示例:
import shutil
src_file = "source_file.txt"
dst_file = "destination_file.txt"
## 复制文件并保留元数据
shutil.copy2(src_file, dst_file)与 shutil.copy() 不同,shutil.copy2() 将尽量保留原始文件的权限、访问时间和修改时间。这对于需要保留文件元数据的场景非常有用,例如备份文件或需要跟踪文件属性的应用程序。请注意,某些操作系统和文件系统可能会限制某些元数据的复制,取决于系统的特定限制。
总之,shutil.copy2() 是一个复制文件并尽量保留文件元数据的有用函数。
copytree()
shutil.copytree(src, dst): 递归地复制整个目录树,包括所有文件和子目录。
shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False) 函数用于递归复制整个目录树,包括目录中的所有文件和子目录。它可以将一个目录及其内容复制到目标目录,创建一个完整的目录副本。
参数:
src:要复制的源目录的路径。dst:复制后的目标目录的路径。symlinks:如果为True,则会复制符号链接指向的文件而不是符号链接本身。默认为False。ignore:可选的回调函数,用于指定要在复制过程中忽略的文件或目录。该回调函数接受单个参数,即当前目录的路径,如果返回一个列表,列表中的项目将被忽略。默认为None。copy_function:用于复制文件的函数,默认为shutil.copy2,它会尽可能地保留文件元数据。您可以将其设置为其他复制函数,以控制如何复制文件。ignore_dangling_symlinks:如果为True,则在复制过程中忽略指向不存在的目标的符号链接。默认为False。
示例:
import shutil
src_directory = "/path/to/source_directory"
dst_directory = "/path/to/destination_directory"
## 递归复制整个目录树
shutil.copytree(src_directory, dst_directory)上述示例将递归复制 src_directory 目录及其所有内容到 dst_directory。如果 dst_directory 已经存在,它将引发 FileExistsError,除非您在调用 shutil.copytree() 时指定了新的目标目录。
shutil.copytree() 是一个非常方便的函数,用于创建目录的副本,包括其中的文件和子目录。
copyfile()
shutil.copyfile(src, dst) 函数用于复制单个文件的内容从源路径 src 到目标路径 dst,而不会复制文件的元数据(如权限、时间戳等)。这个函数适用于需要简单复制文件内容的情况。
参数:
src:要复制的源文件的路径。dst:复制后的目标文件的路径。
示例:
import shutil
src_file = "source_file.txt"
dst_file = "destination_file.txt"
## 复制文件内容
shutil.copyfile(src_file, dst_file)上述示例将 source_file.txt 的内容复制到 destination_file.txt,但不会复制文件的元数据。
与 shutil.copy() 和 shutil.copy2() 不同,shutil.copyfile() 仅复制文件的内容,而不包括元数据。如果您需要保留元数据,可以使用 shutil.copy() 或 shutil.copy2() 函数。
copymode()
复制少部分元数据
shutil.copymode(src, dst) 函数用于复制文件的权限模式(mode)从源文件 src 到目标文件 dst,而不复制文件的内容或其他元数据。这个函数通常用于保留文件的权限设置,而不改变文件的内容。
参数:
src:要复制权限模式的源文件的路径。dst:目标文件的路径,其权限模式将从源文件复制。
示例:
import shutil
src_file = "source_file.txt"
dst_file = "destination_file.txt"
## 复制源文件的权限模式到目标文件
shutil.copymode(src_file, dst_file)上述示例将源文件 source_file.txt 的权限模式复制到目标文件 destination_file.txt,而不复制文件内容或其他元数据。
shutil.copymode() 是一个用于复制文件权限的方便函数,可以用于确保目标文件具有与源文件相同的权限设置,而不影响文件的内容或其他属性。
copystat()
复制大部分元数据
shutil.copystat(src, dst) 函数用于将源文件或目录 src 的文件状态信息(metadata)复制到目标文件或目录 dst,包括权限、时间戳等。这个函数不复制文件的内容,只复制元数据。
参数:
src:要复制元数据的源文件或目录的路径。dst:目标文件或目录的路径,元数据将复制到这里。
示例:
import shutil
src_path = "source_file.txt"
dst_path = "destination_file.txt"
## 复制源文件的元数据到目标文件
shutil.copystat(src_path, dst_path)上述示例将源文件 source_file.txt 的元数据(如权限、时间戳等)复制到目标文件 destination_file.txt,但不复制文件的内容。
shutil.copystat() 是一个有用的函数,用于在不影响文件内容的情况下复制文件的元数据。这对于需要保留文件属性的操作非常有用。
移动、重命名文件或目录
move()
shutil.move(src, dst): 移动文件或目录从src到dst,还可以可以用于重命名文件或目录。
shutil.move(src, dst) 函数用于移动文件或目录从源路径 src 到目标路径 dst。这个函数不仅可以用于移动文件,还可以用于重命名文件或目录。如果目标路径已存在,它将替换目标路径上的文件或目录。
参数:
src:要移动的源文件或目录的路径。dst:移动后的目标文件或目录的路径。
示例:
import shutil
src_path = "source_file.txt"
dst_path = "destination_file.txt"
## 移动文件,也可用于重命名
shutil.move(src_path, dst_path)上述示例将 source_file.txt 移动到 destination_file.txt,从而可以用于文件的重命名操作。
如果 src 是一个目录,shutil.move() 将递归移动整个目录树到目标位置。如果目标路径 dst 已经存在,shutil.move() 将替换目标路径上的文件或目录。
shutil.move() 是一个有用的函数,用于在文件系统中移动或重命名文件和目录。请注意,在移动文件或目录时,您应该小心,以免意外覆盖重要的数据。
删除文件或目录
remove()
shutil.remove(path): 删除文件。
shutil.remove(path) 函数用于删除指定路径下的文件。这个函数可以用来删除单个文件,但不能删除目录。如果您需要删除目录及其内容,可以使用 shutil.rmtree() 函数。
参数:
path:要删除的文件的路径。
示例:
import shutil
file_to_delete = "file_to_delete.txt"
## 删除文件
shutil.remove(file_to_delete)上述示例将删除名为 file_to_delete.txt 的文件。
请小心使用 shutil.remove(),因为它会永久删除文件,而且没有回收站。在删除文件之前,请确保您确实想要删除它,以避免不必要的数据丢失。如果需要删除整个目录及其内容,可以使用 shutil.rmtree() 函数。
rmtree()
shutil.rmtree(path): 递归删除目录及其内容。
shutil.rmtree(path, ignore_errors=False, onerror=None) 函数用于递归地删除指定路径下的目录及其内容。这个函数可以用于删除整个目录树,包括目录中的文件和子目录。
参数:
path:要删除的目录的路径。ignore_errors:如果设置为True,则即使在删除目录时出现错误,也会继续执行。默认为False。onerror:一个可选的回调函数,用于处理在删除过程中出现的错误。如果未提供此参数,将引发OSError异常以指示错误。
示例:
import shutil
directory_to_delete = "directory_to_delete"
## 递归删除目录及其内容
shutil.rmtree(directory_to_delete)上述示例将递归删除名为 directory_to_delete 的目录以及其中的所有文件和子目录。
要小心使用 shutil.rmtree(),因为它会永久删除目录及其内容,没有回收站。确保在使用该函数之前备份重要数据,并谨慎使用 ignore_errors 参数,以避免不必要的数据丢失。如果需要删除单个文件,可以使用 shutil.remove() 函数。
获取文件和目录信息
disk_usage()
shutil.disk_usage(path): 返回指定路径的磁盘使用信息。
shutil.disk_usage(path) 函数用于获取指定路径所在磁盘分区的使用情况信息。这个函数返回一个包含三个元素的命名元组,表示磁盘分区的总容量、已用容量和可用容量(以字节为单位)。
参数:
path:要查询磁盘使用情况的路径。通常可以提供分区的根目录路径。
返回值:
- 返回一个命名元组,包含以下三个字段:
total:表示磁盘分区的总容量。used:表示磁盘分区已经使用的容量。free:表示磁盘分区的可用容量。
示例:
import shutil
disk_usage = shutil.disk_usage("/path/to/disk/partition")
total_space = disk_usage.total
used_space = disk_usage.used
free_space = disk_usage.free
print(f"Total Space: {total_space / (1024**3):.2f} GB")
print(f"Used Space: {used_space / (1024**3):.2f} GB")
print(f"Free Space: {free_space / (1024**3):.2f} GB")上述示例演示了如何使用 shutil.disk_usage() 函数来获取磁盘分区的使用情况信息,并将结果以可读的方式打印出来。
这个函数在需要获取磁盘空间信息以进行存储管理、磁盘监控或其他磁盘相关操作时非常有用。请确保提供正确的路径以获取相应磁盘分区的信息。
stat()
shutil.stat(path): 获取文件或目录的元数据信息,如大小、创建时间等。
shutil.stat(path) 函数用于获取指定路径下文件或目录的元数据(metadata)信息。这个函数返回一个 os.stat_result 对象,包含有关文件或目录的各种属性信息,如大小、权限、时间戳等。
参数:
path:要获取元数据信息的文件或目录的路径。
返回值:
- 返回一个
os.stat_result对象,包含有关文件或目录的元数据信息。
示例:
import shutil
file_path = "example_file.txt"
## 获取文件的元数据信息
file_stat = shutil.stat(file_path)
print(f"文件路径:{file_path}")
print(f"大小:{file_stat.st_size} 字节")
print(f"权限:{file_stat.st_mode}")
print(f"创建时间:{file_stat.st_ctime}")
print(f"修改时间:{file_stat.st_mtime}")上述示例演示了如何使用 shutil.stat() 函数获取文件的元数据信息,包括文件大小、权限、创建时间和修改时间等。
这个函数对于需要访问文件或目录的元数据信息的操作非常有用,例如在处理文件时需要检查其属性或时间戳。请注意,返回的元数据信息可能因操作系统而异,因此具体字段和值可能会有所不同。要获取特定属性的信息,您可以查看 os.stat_result 对象的属性。
压缩和解压缩文件
make_archive()
shutil.make_archive(base_name, format, root_dir): 创建一个归档文件(如zip、tar等)。
shutil.make_archive(base_name, format, root_dir=None, base_dir=None) 函数用于创建一个归档文件,它将指定目录及其内容打包为一个压缩文件或归档文件,例如 ZIP 文件、tarball(tar.gz)等。这个函数是在 shutil 模块中提供的。
参数:
base_name:归档文件的基本名称,通常不包括文件扩展名。例如,如果您想要创建一个名为 “archive” 的 ZIP 文件,那么base_name应为 “archive”。format:指定要创建的归档文件的格式,可以是 “zip”、“tar”、“gztar”(gzip 压缩的 tarball)、“bztar”(bzip2 压缩的 tarball)或 “xztar”(xz 压缩的 tarball)之一。root_dir:要归档的根目录的路径。默认情况下,将使用当前工作目录作为根目录。base_dir:在归档文件中存储的相对路径。默认情况下,将使用根目录中的所有内容。如果指定了base_dir,则只有base_dir中的内容将被归档。
返回值:
- 返回创建的归档文件的完整路径。
示例:
import shutil
## 创建一个名为 "my_archive.zip" 的 ZIP 归档文件,包括当前工作目录下的所有内容
archive_path = shutil.make_archive("my_archive", "zip")
print(f"归档文件路径:{archive_path}")上述示例将创建一个名为 “my_archive.zip” 的 ZIP 归档文件,其中包含当前工作目录下的所有文件和子目录。
shutil.make_archive() 是一个方便的函数,用于将文件和目录打包成归档文件,以便于传输、存储或备份。请注意,具体支持的格式可能因操作系统和 Python 安装的不同而有所不同。
unpack_archive()
shutil.unpack_archive(filename, extract_dir): 解压缩归档文件。
shutil.unpack_archive(filename, extract_dir=None, format=None) 函数用于解压缩归档文件,将归档文件的内容提取到指定的目录中。这个函数支持多种归档格式,如 ZIP 文件、tarball(tar.gz)、bzip2 压缩的 tarball(tar.bz2)、xz 压缩的 tarball(tar.xz)等。
参数:
filename:要解压的归档文件的文件名,可以包括文件路径。extract_dir:可选参数,指定要将归档文件的内容提取到的目标目录。如果未指定,则会将内容提取到当前工作目录。format:可选参数,用于指定归档文件的格式。如果未指定,将根据文件名的扩展名自动识别格式。
返回值:
- 无返回值,函数将归档文件的内容解压缩到指定目录。
示例:
import shutil
## 解压缩名为 "my_archive.zip" 的 ZIP 归档文件到当前工作目录
shutil.unpack_archive("my_archive.zip")
## 解压缩名为 "my_tarball.tar.gz" 的 tarball 到指定目录 "/path/to/extracted_files"
shutil.unpack_archive("my_tarball.tar.gz", extract_dir="/path/to/extracted_files")上述示例演示了如何使用 shutil.unpack_archive() 函数来解压缩归档文件。您可以根据归档文件的格式和提取目录的需求,选择相应的参数值。如果不指定提取目录,文件将被解压到当前工作目录。
这个函数非常有用,可以用于从归档文件中提取数据,以便在后续的操作中使用。