【问题标题】:Exception handling in version agnostic code版本无关代码中的异常处理
【发布时间】:2018-05-16 02:06:11
【问题描述】:

我手头有一个简单的任务...处理异常,以便在 python2.x/3.x 之间使用 urllib/urllib2 时代码不会抛出 IncompleteRead

python2

try:
    page = urllib2.urlopen(urls).read()
except httplib.IncompleteRead, e:
    page = e.partial

python3

try:
    page = request.urlopen(urls).read()
except (http.client.IncompleteRead) as e:
    page = e.partial

现在由于模块本身不同,如何进行尝试,除非我不知道我的用户将运行哪个 python 版本?

我也无法在我的 try-except 中检查 python 版本...或者我可以吗?

有没有办法捕捉它的超类,所以它对于两个 python 版本都一样?如果是,怎么做?

【问题讨论】:

  • 可能是更好的方法,但您可以使用sys.version检查哪个版本的python正在运行您的脚本
  • 好的...但是一旦我得到版本,我该如何处理异常?我的代码中只有一个 try-except 块...
  • 除非您需要 Python 2.5,否则您可以在 2.x 中使用新式 except: 语句。

标签: python python-3.x python-2.7 exception-handling


【解决方案1】:

你可以:

try:
    from httplib import IncompleteRead
    import urllib2 as httpclient
except ImportError:
    from http.client import IncompleteRead
    import request as httpclient

然后使用:

try:
    page = httpclient.urlopen(urls).read()
except IncompleteRead as e:
    page = e.partial

在 python2 和 python3 中。

【讨论】:

    【解决方案2】:

    除非您需要 Python 2.5,否则您可以使用新样式 except: 2.x 中的语句。

    所以,唯一的区别是模块名称。您可以手动try,如Sraw's answer。但是您可能应该使用sixfuturizemodernize,正如the official porting docs 和大多数其他双版本控制和移植指南所推荐的那样,这正是他们擅长的事情。


    six.moves:

    from six.moves import http_client
    from six.moves import urllib_request
    
    try:
        page = urllib_request.urlopen(urls).read()
    except http_client.IncompleteRead as e:
        page = e.partial
    

    或者,future:

    from future import standard_library
    standard_library.install_aliases()
    import http.client
    import urllib.request, urllib.error, urllib.parse
    
    try:
        page = urllib.request.urlopen(urls).read()
    except http.client.IncompleteRead as e:
        page = e.partial
    

    或者,更好的是,只需编写 2.7 代码:

    import httplib
    import urllib2
    
    try:
        page = urllib2.urlopen(urls).read()
    except httplib.IncompleteRead as e:
        page = e.partial
    

    …然后在上面运行futurize,它会自动给你上面的future代码。

    【讨论】:

    • 感谢移植文档的链接,版本/功能检测之间的有趣区别。看来我的回答是不好的做法,已被删除。
    • @chrisz 好吧,这是某些事情的正确答案,但我认为总的来说 Sraw 的版本被认为更 Pythonic。 (就像 EAFP 通常击败 LBYL 一样。)
    • 我只用它来告诉人们我的东西不能用 Python 2 运行,这看起来不错,但我完全同意。
    • @chrisz 对于我不为 PyPI 打包的任何东西,我只是 assert.version_info >= (3,6) 或其他任何东西。这已经足够好了,如果有人抱怨“它不起作用”并告诉我错误的任何部分,我可以告诉他们“是的,那是因为 Python 2.3 不是 >= 3.6”而不是“那个集合理解看起来完全有效,如果没有更多信息,我不知道该告诉你什么。”
    【解决方案3】:

    您可以尝试...除了在 init 模块中导入,然后将代码拆分为 python2 和 python3 模块:

    try:
        import urllib2
        pyver2()
    except ModuleNotFoundError:
        import requests
        pyver3()
    

    哦,请求没有做你想做的事,也许你的意思是“请求”,而请求没有你需要使用“get()”的“urlopen”方法。

    【讨论】:

    • 我很确定 OP 确实是指 3.x stdlib 附带的 urllib 包中的 request 模块,它确实具有 urlopen 函数。
    • 另外,这不会将代码拆分为两个模块,而是拆分为同一个模块中的两个函数。 (这意味着如果您想在 3.x 模块中使用仅限 3.x 的语法,这将无济于事。)像这样并行维护两个模块通常是不值得的。这是 3.0-3.1 中推荐的解决方案(特别是如果您可以在安装时运行2to3 以生成 3.x 版本(如果需要)),但是如果您环顾 PyPI,几乎没有人从 3.3 左右开始这样做,并且在 Nick Coghlan 的网站上,有一篇很好的博文解释了原因。
    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2021-10-21
    相关资源
    最近更新 更多