如何在Python包中跳过中间模块直接导入子模块?
解决Python包导入层级隐藏问题
首先得提个关键注意点:Python的模块名不能是纯数字(比如1.py、3.py),这违反了Python标识符的命名规则,直接使用会触发语法错误。所以先建议你把这类模块改名,比如1.py改成module1.py、3.py改成module3.py,下面的示例都基于改名后的结构讲解。
为什么from .A import *无效?
你之前尝试的from .A import *只会导入A模块中__all__指定的成员(如果没定义__all__,则导入所有非下划线开头的成员),但不会把A目录下的子模块(比如module1.py)本身导入到root的命名空间里。要实现隐藏中间层级的效果,需要显式地把子模块绑定到root的命名空间。
具体解决步骤
假设你的目录结构修改后是这样:
root/ __init__.py A/ __init__.py module1.py # 原1.py module2.py # 原2.py B/ __init__.py module3.py # 原3.py
修改
root/__init__.py:
在这个文件里显式导入需要暴露的子模块,直接绑定到root的命名空间:# 把A下的module1导入到root模块 from .A import module1 # 把B下的module3导入到root模块 from .B import module3验证导入效果:
现在你就可以直接从root导入目标模块了:# 导入module1模块 from root import module1 # 从module3导入a_func from root.module3 import a_func
如果坚持要用数字命名模块(不推荐)
如果因为特殊需求必须保留1.py、3.py这类名字,你需要用importlib来动态导入,因为直接用from .A import 1是语法错误。在root/__init__.py中写:
import importlib # 动态导入A下的1.py模块,并绑定到root的命名空间(用合法的名字比如m1) m1 = importlib.import_module('.A.1', package='root') # 如果一定要用数字作为属性名(不建议,不符合PEP8) globals()['1'] = importlib.import_module('.A.1', package='root') globals()['3'] = importlib.import_module('.B.3', package='root')
但这种方式会让代码可读性变差,还可能引发潜在问题,所以强烈建议遵循Python的命名规范修改模块名。
关于setuptools配置
你当前的packages=['root', 'root.A', 'root.B']配置是没问题的,不需要修改,它能正确识别所有子包。
内容的提问来源于stack exchange,提问作者darkpirate
相关产品推荐
相关产品推荐

