我有一个具有以下目录结构的python包
package/
├── __init__.py
└── subpackage_A/
├── __init__.py
├── moduleA.py
└── moduleB.py
现在,我想将subpackage_A
的名称更改为subpackage_B
,同时保持旧名称可用,否则很多脚本都会中断。所以这应该是可能的:
from package.subpackage_B import moduleA
from package.subpackage_B.moduleB import ClassB
# This should, if possible, display a deprecation warning
from package.subpackage_A import moduleA
我试图将新软件包简单地导入名为subpackage_A
的模块中,但这不起作用:
# File: package/subpackage_A.py
# This does not work:
from package.subpackage_B import * # Import everything from the new module
# This is also not working:
sys.modules[__name__] = __import__('package.subpackage_A')
如果脚本试图从旧位置导入ModuleNotFoundError
,则第一个版本将导致moduleA
:
from package.subpackage_A import moduleA
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'package.subpackage_A.moduleA'
如何在不破坏向后兼容性的情况下重命名模块?该解决方案应该适用于python 3.5及更高版本。
答案 0 :(得分:1)
问题在于subpackage_B/__init__.py
不导入moduleA
和moduleB
,因此import *
不导入任何内容。
使用显式导入:
from .subpackage_B import moduleA, moduleB
或修改subpackage_B/__init__.py
以显式进行导入:
from . import moduleA, moduleB
关于使用subpackage_A时发出警告:您可以简单地触发它。在subpackage_A
内部:
import warnings
warnings.warn('The name subpackage_A is deprecated. Please use subpackage_B')
from .subpackage_B import *
答案 1 :(得分:1)
如果您使用的是Python 3.7+,则可以使用PEP562中定义的模块级别__getattr__
。
您已将subpackageA重命名为subpackageB,然后在package/__init__.py
中输入以下内容
from . import subpackageB
from warnings import warn
def __getattr__(name):
if name == 'subpackageA':
warn('subpackageA has been renamed to subpackageB')
return subpackageB
raise AttributeError('No module named ' + name)
然后在使用包裹时
>>> from package import subpackageB
>>> from package import subpackageA
/path/to/package/__init__.py:5: UserWarning: subpackageA has been renamed subpackageB
warn('subB has been renamed subA')
>>> subpackageA == subpackageB
true
>>>