繁体   English   中英

我应该如何在 Python 中捕获由 `with open(filename)` 引发的异常?

[英]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...

这个问题与这个较早的问题不同, 较早的问题是关于编写上下文管理器,而不是使用熟悉with open

我可以捕获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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM