[英]How should I catch exceptions raised by `with open(filename)` in Python?
尝试在 Python 中打开文件的行为可能会引发异常。 如果我使用with
语句打开文件,是否可以捕获由open
调用和相关__enter__
调用引发的异常而不捕获由with
块中的代码引发的异常?
try:
with open("some_file.txt") as infile:
print("Pretend I have a bunch of lines here and don't want the `except` below to apply to them")
# ...a bunch more lines of code here...
except IOError as ioe:
print("Error opening the file:", ioe)
# ...do something smart here...
我可以捕获open调用抛出的异常和相关的
__enter__
调用,而不会捕获with块中代码引发的异常吗?
是:
#!/usr/bin/env python3
import contextlib
stack = contextlib.ExitStack()
try:
file = stack.enter_context(open('filename'))
except OSError as e:
print('open() or file.__enter__() failed', e)
else:
with stack:
print('put your with-block here')
使用默认的open()
函数, __enter__()
不应引发任何有趣的异常,因此代码可以简化:
#!/usr/bin/env python
try:
file = open('filename')
except OSError as e:
print('open() failed', e)
else:
with file:
print('put your with-block here')
如果错误与打开文件有关(例如,如果文件不存在),则调用将引发它自己open
,而不是__enter__
。 在这种情况下,您可以通过将open
调用与with块分开来捕获它:
try:
myFile = open('some_file.txt')
except IOError:
print("Oh my snakes and garters!")
with myFile:
# do stuff
# This will be True
print(myFile.closed)
正如您链接到的问题(以及其他相关问题)所暗示的那样,您无法将__enter__
的异常与with
块中的异常分开。 但是,由于这个原因,在大多数情况下,尝试执行可能在__enter__
引发异常的复杂内容的上下文管理器无论如何都可能是一个脆弱的设计。 我认为file.__enter__
只返回文件(如本页所示 ),虽然我找不到任何保证这一点的文档。
在 Python 3 中,IOError 是 OSError 的别名。 要验证,请运行代码:
IOError is OSError
---
True
OSError 是文件 I/O 异常的父类。
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
OSError.__subclasses__()
---
[ConnectionError,
BlockingIOError,
ChildProcessError,
FileExistsError,
FileNotFoundError,
IsADirectoryError,
NotADirectoryError,
InterruptedError,
PermissionError,
ProcessLookupError,
TimeoutError,
io.UnsupportedOperation,
signal.ItimerError,
socket.herror,
socket.gaierror,
socket.timeout,
ssl.SSLError,
shutil.Error,
shutil.SpecialFileError,
shutil.ExecError,
shutil.ReadError,
urllib.error.URLError,
gzip.BadGzipFile]
因此,如果需要详细信息,请捕获 OSError 并检查确切的类。
try:
with open('hoge') as f:
pass
except OSError as e:
print(f"{type(e)}: {e}")
---
<class 'FileNotFoundError'>: [Errno 2] No such file or directory: 'hoge'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.