在Python 2和Python 3中捕获破碎的管道

时间:2016-01-11 09:40:44

标签: python python-3.x exception python-2.x

我尝试编写一些代码来捕获Broken Pipe Error。代码应该在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://stackoverflow.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。由于{3.}}在Python 3.x中已被弃用,因此在不久的将来Python 3.0中可能出现类似的问题。

如何使此代码在Python 2.x和Python 3.x中运行?

2 个答案:

答案 0 :(得分:6)

如果您关心的是管道错误,那么您可能想要捕获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()

如果你关心的不仅仅是破损的管道,那么这个答案是恰当的,并且是惯用的。

答案 1 :(得分:4)

您可以尝试使用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