当用户导入不赞成使用的变量时,引发自定义ImportError

时间:2018-08-20 13:50:53

标签: python python-3.x python-import

我写了一个程序包,其中一个子模块包含我要删除的模块级变量deprecated_var,因为这是一个可怕的错误。

mypkg
  - mymodule
    - __init__.py

但我不仅要给我的最终用户一个通用的ImportError,还要打印一条消息,说明他们的导入已被弃用,应该怎么做。所以代替:

>>> from mypkg.mymodule import deprecated_var
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'deprecated_var'

我希望用户看到这样的内容:

>>> from mypkg.mymodule import deprecated_var
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: mypkg.mymodule.deprecated_var was removed. Replace 
  with "from foo.bar import Baz; deprecated_var = Baz()"

我该如何实现?

2 个答案:

答案 0 :(得分:2)

我认为在python 3.7之前这是不可能的。

但是,在python 3.7或更高版本中,可以通过使用PEP562中添加的模块级别__getattr__来实现。

您将这样使用:

#_deprecated_vars is a dict of keys -> alternatives (or None)
_deprecated_vars: Dict[str, Optional[str]] = {
        'deprecated_var': 'from foo.bar import Baz; deprecated_var = Baz()', 
        'other_deprecated_var': None
    }

def __getattr__(name):
    if name in _deprecated_vars:
        alt_text = '{name} was removed from module {__name__}'
        replace_text = _deprecated_vars[name]
        if replace_text is not None:
           alt_text += f'. Replace with {replace_text!r}.'
        raise AttributeError(alt_text)
    raise AttributeError(f"module {__name__} has no attribute {name}")

但是,我不确定这是否适用于您的from a.b import deprecated_var用例。 import a.b; a.b.deprecated_var的更多功能。参见前者的其他答案。

答案 1 :(得分:2)

对于您的特定示例,您可以使用以下内容:

mymodule/__init__.py

#deprecated_var = 5
replacement_var = 6

mymodule/deprecated_var.py

raise ImportError("deprecated_var is deprecated. Use mypkg.mymodule.replacement_var instead")

虽然在直接导入变量时会引发自定义ImportError

>>> from mymodule import deprecated_var
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../mymodule/deprecated_var.py", line 1, in <module>
    raise ImportError("deprecated_var is deprecated. Use mypkg.mymodule.replacement_var instead")
ImportError: deprecated_var is deprecated. Use mypkg.mymodule.replacement_var instead

作为模块属性访问它时不执行任何操作。或者,它抛出一个AttributeError而不是弃用警告:

>>> import mymodule
>>> mymodule.deprecated_var
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'mymodule' has no attribute 'deprecated_var'