我写了一个包P.在P的根处有一个模块m0。 在P内的某处有模块m1,m2,...需要从m0
导入当然,我可以在每个模块中写一下:
from P.m0 import ...
但是,如果我更改P的名称,我必须重新访问所有地方并重写这些声明。
我也可以使用相对导入,但如果我在包层次结构中移动一个不同级别的模块,我必须修复点数。
还有一些其他原因,但是底线,我真的想说从我的包的根目录中的模块m0导入,表达这个的最佳方式是什么?
答案 0 :(得分:1)
那是不可能的。
但是,如果你执行主要的重构,你必须更新一些相对导入的子包之间的模块移动不是一个大问题。
如果您不使用相对导入,则同样适用于重命名顶级包名称 - 甚至可以通过搜索和替换所有文件来快速完成。
答案 1 :(得分:0)
如果你愿意稍微修改一下你的问题,你就可以侥幸成功。
如果您的包裹的唯一入口点受到控制;例如您只需通过调用testsuite package/.../module.py
来执行某些操作来测试您的代码
那么你可以确保你做的第一件事是import firstthing
,而你在package / firstthing.py中有:
import sys
import os.path
packageDir = os.path.split(__name__)[0]
sys.path[:] = sys.path+[packageDir] # or maybe you want it first...
主要警告是,如果不通过入口点,您将无法运行python文件。我总是想为我在python中编写的每个项目(为了使相对导入很好地工作)这样做,但我个人觉得这很不方便,我只是放弃了。
还有第二种选择。指定您的包在python路径中需要另一个包不是 不合理的。这个包可能是一个执行主要黑客攻击的实用程序包。例如,如果包的名称是“x”,您可以执行import x
,它将使用inspect模块对解释器堆栈执行反射,让您确定从哪个模块导入它。然后你可以通过上升父目录来做一个“向后os.walk”,直到你找到你的包的根(通过检查一些特殊的指示文件,或清单,或什么)。然后代码将通过sys.path
以编程方式执行python路径的上述修改。它与上面的相同,但您可以自由地执行诸如运行任何python文件而无需经历可怕的入口点。
如果你对shell环境有极大的控制权,你也可以只增加$ PYTHONPATH来包含你的包目录,但这在很多方面都非常脆弱,而且相当不优雅。