4.1 文件关闭和错误处理
有时候在读取文件时会出错或者抛出异常,而文件却没有被关闭。这可能导致内存泄漏或者
file handler
泄漏。因此文件操作需要放在try-except
块中。
假设你有以下代码:
file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
file.close() # 关闭文件
需要把它放在try-except
块中:
try:
file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
file.close() # 关闭文件
except FileNotFoundError:
print("File not found")
file.close() # 关闭文件
为了不多次调用close()
方法,可以将其放在finally
块中:
try:
file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # 关闭文件
这个代码看起来不错,但……不工作,因为变量file
只在try
块中定义,在except
和finally
块中不可用。
所以我们需要把变量定义在更高的层级:
file = None
try:
file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # 关闭文件
这个解决方案更好,但也有缺点。比如,如果文件无法打开,变量file
将保持None
。而关闭文件的尝试会引发错误——企图对不存在的对象调用close()
方法。
因此需要在调用close()
方法前增加检查:
file = None
try:
file = open('example.txt', 'a') # 打开文件
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
if file:
file.close() # 关闭文件
如果你惊讶于3行代码变成了9行,你并不孤单。幸运的是,已有解决方案,我们接下来会谈论。
4.2 with
语句
Python中的with
语句提供了一种便捷的资源管理方式,比如文件,确保在with
块结束后自动关闭。这样简化了代码,防止了资源泄漏,比如未关闭的文件。
with
语句的一般语法:
with 表达式 as 变量:
操作变量
with
语句用于
给代码块包装一个上下文管理器。使用with
时,Python自动调用上下文管理器对象的__enter__()
和__exit__()
方法,这简化了
资源管理。
使用with
进行文件操作的示例:
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
在这个例子中,文件example.txt
以写入模式打开,文件名绑定到变量file
。with
中的代码块
在完成所有写操作后会自动关闭文件。
4.3 自动关闭文件
使用with
语句的一个主要优势是
在代码块结束后自动关闭文件。即使在发生异常时也会关闭文件,这使得代码更安全可靠。
自动关闭文件示例:
try:
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
# 抛出异常,检查文件是否仍然会被关闭
raise Exception("Something went wrong")
except Exception as e:
print(f"Caught an exception: {e}")
# 在这里文件已经关闭
操作文件时一定要使用with
语句。这简单且能避免许多错误。
4.4 with
语句的内在机制
with
语句的根本在于__enter__()
和__exit__()
方法,使用作为上下文管理器的类必须实现这些方法。
要让对象能用在with
语句中,它必须实现__enter__()
和__exit__()
方法。这些方法定义了进入和退出上下文时的行为。
__enter__()
方法
__enter__()
方法在进入with
块时调用。
它初始化资源并返回将绑定到as
后指定的变量的对象。
__exit__()
方法
__exit__()
方法在退出with
块时调用。它进行结束操作,比如释放资源或关闭文件。该方法接受三个参数:exc_type
,exc_val
和exc_tb
,这些参数包含异常信息(如果发生异常)。
-
exc_type
:异常类型(例如,ZeroDivisionError
)。 -
exc_val
:异常值(例如, 错误信息)。 exc_tb
:异常的堆栈跟踪。
如果__exit__()
方法返回True
,
则异常将被抑制。如果返回
False
,异常将被重新抛出。
示例:
class MyContextManager:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"An exception occurred: {exc_type}, {exc_val}")
return False # 异常不被抑制
with MyContextManager() as manager:
print("Inside the with block")
GO TO FULL VERSION