使用模块中的异常而不显式导入它

时间:2013-08-02 10:30:12

标签: python python-2.7 package python-import

我有一个实用程序模块utils.py,它使用requests来执行某些任务。在客户端代码(使用utils)中,我需要处理requests抛出的异常,但我想避免隐式导入requests(在客户端中,即)。我怎样才能做到这一点?

utils.py是(简化)

 import requests

 def download(url):
     # stuff
     return requests.get(url)

我希望client.py类似于

 import utils  # <-- no "import requests"

 try:
      utils.download(whatever)
 except HTTPError:  # <-- not "requests.exceptions.HTTPError"
      do stuff

except utils.something也可以。该名称不需要是全局的。我想要的是避免在客户端的任何地方提及requests

对于那些疑惑的人来说,这只是一个关注点分离的问题。 client.py不应该关心如何实现utils.download以及它使用的底层低级库。

3 个答案:

答案 0 :(得分:3)

简短回答:你不能(或者至少不应该)。

当然,没有理由避免导入您想要使用的任何内容。这就是Python的工作方式,旨在发挥作用,并且效果最佳。

如果你真的想分开关注点,请让download()捕获异常,并抛出一个新的utils.DownloadError异常。

def download(...):
    try:
        ...
    except HTTPError as e:
        raise DownloadError() from e

编辑:

答案很长:你可以通过链导入异常来实际做到这一点 - 但我强烈建议不要这样做 - 它只会使代码不那么清晰。

例如:如果您在from requests.exceptions import HTTPErrorutils.py import utils,那么您可以utils.HTTPError并使用requests

但是,我相信,这可能会更加脆弱 - 更不用说迂回而且难以跟踪代码中的意图。我仍然强烈反对它。

从关注点分离的角度来看 - 它可能会阻止你提到{{1}},但它仍然依赖于异常,所以它所做的就是隐藏关注点而不是将它分开。

答案 1 :(得分:1)

我知道这是一种破旧方式,但我会做两件事之一:

  • 处理utils.py或...
  • 中的例外情况
  • 请注意utils.py中的异常,并在request.exceptions.HTTPError
  • 的情况下重新引发HTTPError

你会对这两个中的任何一个感到满意吗?

答案 2 :(得分:0)

您可以使用utils.requests.exceptions.HTTPError,但无法避免“提及”requests。你所能做的就是以环形交叉口,容易出错的方式提及它。