在 Python 2 和 Python 3 中捕获断管
Posted
技术标签:
【中文标题】在 Python 2 和 Python 3 中捕获断管【英文标题】:Catch Broken Pipe in Python 2 AND Python 3 【发布时间】:2016-01-11 09:40:44 【问题描述】:我尝试编写一些代码来捕获 Broken Pipe 错误。代码应在 Python 2.x 和 Python 3.x 中运行。
在 Python 2.x 中,损坏的管道由 socket.error
表示
socket.error: [Errno 32] Broken pipe
这在 Python 3.x 中已更改 - 损坏的管道现在是 BrokenPipeError
BrokenPipeError: [Errno 32] Broken pipe
异常处理的语法也发生了一些变化(参见https://***.com/a/34463112/263589),所以我需要做的是:
try:
do_something()
except BrokenPipeError as e: # implies Python 3.x
resolve_for_python2()
except socket.error as e:
if sys.version_info[0] == 2: # this is necessary, as in Python >=3.3
# socket.error is an alias of OSError
# https://docs.python.org/3/library/socket.html#socket.error
resolve_for_python3()
else:
raise
(至少)还有一个问题:在 Python 2.x 中没有BrokenPipeError
,所以每当do_something()
中出现异常时,Python 2.x 都会抛出另一个异常并抱怨它不知道BrokenPipeError
。由于socket.error
在 Python 3.x 中已被弃用,在不久的将来 Python 3.x 中可能会出现类似的问题。
我可以怎样做才能让这段代码在 Python 2.x 和 Python 3.x 中运行?
【问题讨论】:
看看python-future.org/compatible_idioms.html,他们展示了异常处理。 newbebweb.blogspot.in/2012/02/… 这里是 谢谢!但是python-future.org/compatible_idioms.html#catching-exceptions 没有解释如何捕获 Python 2 或 Python 3 中不存在但在其他版本中是强制性的异常。 @RajarshiDas 这很有趣!如果建议 Python 忽略 SIGPIPE 错误,您是否想说根本不需要捕获损坏的管道? 【参考方案1】:如果您只关心损坏的管道错误,那么您可能想要捕获socket.error
并简单地检查它是否确实是损坏的管道错误。
您可以使用异常的 errno
属性来执行此操作,该属性在 Python 2 和 Python 3 中都存在,这意味着,您不需要不同的 Python 2 与 3 逻辑(我认为意图是这样更清楚):
import socket
import errno
try:
do_something()
except socket.error as e:
if e.errno != errno.EPIPE:
# Not a broken pipe
raise
do_something_about_the_broken_pipe()
如果您关心的不仅仅是损坏的管道,thefourtheye 的回答是恰当且惯用的。
【讨论】:
谢谢!我有点担心socket.error
在 Python 3 中已被弃用。所以如果我更新我的 Python 3 解释器,在(不久的)将来可能还会出现另一个问题......
@speendo 在 Python 标准库本身中有几十个对 socket.error
的引用。当然,它已被弃用,但它不会消失。删除 socket.error
将是一个毫无意义的重大更改,这是 Python 核心开发人员公开表示他们将在未来避免的事情。如果它最终被删除(几十年后?!;)),那么识别和修复错误将是微不足道的,到那时你可能不会再支持 Python 2。【参考方案2】:
您可以尝试使用BrokenPipeError
,如果它抛出NameError
,则回退到socket.error
,就像这样
import socket
try:
expected_error = BrokenPipeError
except NameError:
expected_error = socket.error
然后像这样使用它
try:
1 == 2
except expected_error as ex:
# Handle the actual exception here
【讨论】:
以上是关于在 Python 2 和 Python 3 中捕获断管的主要内容,如果未能解决你的问题,请参考以下文章
仅需6道题轻松掌握Python异常捕获 | Python技能树征题