重命名python子包,将旧名称标记为已弃用

2024-06-22 08:41:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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,则第一个版本会导致ModuleNotFoundError

from package.subpackage_A import moduleA
Traceback (most recent call last):
...
ModuleNotFoundError: No module named 'package.subpackage_A.moduleA'

如何在不破坏向后兼容性的情况下重命名模块?该解决方案应适用于Python3.5及更高版本。你知道吗


Tags: 模块frompyimport脚本名称packageinit
2条回答

如果您使用的是python3.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
>>>

问题是subpackage_B/__init__.py不导入moduleAmoduleB,所以import *什么也不导入。你知道吗

使用显式导入:

from .subpackage_B import moduleA, moduleB

或者修改subpackage_B/__init__.py以显式执行导入:

from . import moduleA, moduleB

关于在使用子包时发出警告:您可以简单地触发它。内部subpackage_A

import warnings

warnings.warn('The name subpackage_A is deprecated. Please use subpackage_B')

from .subpackage_B import *

相关问题 更多 >