我写了一个程序包,其中一个子模块包含我要删除的模块级变量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()"
我该如何实现?
答案 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'