除了Python之外,写try的最佳方法是什么?

时间:2014-12-21 05:04:09

标签: python try-except

假设我有一个代码片段如下

r = requests.post(url, data=values, files=files)

由于这是在发出网络请求,因此可以从此行抛出一堆异常。为了完整的论点,我也可以有文件读取,发送电子邮件等。为了遇到这样的错误我做

try:
  r = requests.post(url, data=values, files=files)
  if r.status_code != 200:
    raise Exception("Could not post to "+ url)
except Exception as e:
  logger.error("Error posting to " + url)

我用这种方法看到了两个问题。

  1. 我刚刚处理了一个通用异常,并且不知道这行会引发什么样的异常,在python中找到它的最佳方法是什么。
  2. 这使得代码看起来很丑陋,这是非pythonic但很好,只要它健壮并处理所有情况。
  3. 我想知道在python中处理异常的最佳方法是什么。

4 个答案:

答案 0 :(得分:5)

在Python或其他任何地方编写try-except的最佳方法是尽可能地缩小。抓住比你想要处理的更多异常是一个常见的问题!

特别是,我至少会将您的示例代码重写为:

try:
  r = requests.post(url, data=values, files=files)
except Exception as e:
  logger.error("Error posting to %r: %s" % (url, e))
  raise
else:
  if r.status_code != 200:
    logger.error("Could not to %r: HTTP code %s" % (url, r.status_code))
  raise RuntimeError("HTTP code %s trying to post to %r" % (r.status_code, url))

这体现了几个最佳实践,例如:详细的错误消息,总是重新引发您不知道如何专门处理的异常(在记录错误消息以及更多详细信息和异常之后),从不提出某些内容泛型为Exception,& c - 而且,至关重要的是,仅在代码的最窄部分捕获异常,这就是else:try/except子句的含义! - )

如果您希望 - 并且知道如何处理 - 特定的异常,那就更好了 - 您将其他except ThisSpecificProblem as e:子句置于通用except Exception子句之前,该子句记录并重新生成加注。但是(来自Python的Zen - import this在Python解释器提示!) - “错误永远不应该默默传递.//除非明确地沉默。”......你应该只是“明确地保持”错误你完全期待,完全知道如何处理!

答案 1 :(得分:4)

  

我刚刚处理了一个通用例外,并且不知道究竟是什么   这条线会引发异常,找到最好的方法是什么   它在python中。

与往常一样,答案是看the documentation

  

如果出现网络问题(例如DNS失败,请拒绝   连接等),请求将引发ConnectionError异常。

     

在极少数情况下,HTTP响应无效,请求将引发   HTTPError异常。

     

如果请求超时,则会引发超时异常。

     

如果请求超过配置的最大重定向数,则a   引发了TooManyRedirects异常。

     

请求显式引发继承自的所有异常   requests.exceptions.RequestException。

记录引发异常的代码(特别是如果存在自定义异常)。如果文档不明确,您还可以查看source

您的代码很好,除非您应该避免泛型除了子句,因为这些可以隐藏代码的其他问题。除了那些你可以预测的例外情况,你应该让其他人出现并且#34;起来"直到被抓住/记录。

答案 2 :(得分:2)

好吧,回答你的第一个问题,这一行会引发什么样的例外,你就是一步之遥。

您已拨打except Exception as e,但未在任何地方使用ee包含有关您的异常的信息,因此只需添加一点印刷语句

  

print e

它有效:

>>> try:
...     x = int(raw_input('Input: '))
... except Exception as e:
...     print e
... 
Input: 5t
invalid literal for int() with base 10: '5t'
>>> 

我并不完全看到你在2 nd 中提出的问题,你说它是丑陋的/非pythonic,但是你说它没问题。是的,它 很好,在我看来它也是非常pythonic。

答案 3 :(得分:0)

您应尽量避免使用except Exception as e:

为清楚起见,您可以创建一个自定义异常类来处理错误代码= 200场景。

class PostingError(Exception):
    pass

然后只提升PostingError。请尝试仅捕获此错误。通过捕获各种错误,您可能会捕获错误的信息。例如,即使是内存错误也可能被捕获并显示为"错误发布到URL"。

所以这就是最终的样子

try:
  r = requests.post(url, data=values, files=files)
  if r.status_code != 200:
    raise PostingError("Could not post to "+ url)
except PostingError as e:
  logger.error(e)