如何在Python中进行相对导入?
时间:2020-03-05 18:56:05 来源:igfitidea点击:
想象一下这个目录结构:
app/ __init__.py sub1/ __init__.py mod1.py sub2/ __init__.py mod2.py
我正在编码mod1
,我需要从mod2
导入一些东西。我该怎么办?
我从..sub2 import mod2
中尝试过,但是却遇到了"未打包的相对导入尝试"。
我四处搜寻,但只发现"sys.path
操纵"的黑子。有没有一种干净的方法?
编辑:我所有的__init__.py当前为空
Edit2:我正在尝试执行此操作,因为sub2包含在子包之间共享的类(sub1,subX等)。
Edit3:我要查找的行为与PEP 366中描述的相同(感谢John B)
解决方案
回答
我认为我们必须问自己:
- 为什么我需要这样做?
- 我的包裹分离做得好吗?
我不知道背景为何我们要这样做。但是对我来说,更简洁的设计将是具有以下包装结构:
app/ __init__.py sub1/ __init__.py mod1.py sub12/ __init__.py mod2.py
然后,我们只需要执行以下操作:
from sub12 import mod2
回答
每个人似乎都想告诉我们应该做什么,而不仅仅是回答问题。
问题是我们通过将mod1.py作为参数传递给解释器而将模块作为__main__运行。
从PEP 328:
Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
在Python 2.6中,他们添加了相对于主模块引用模块的功能。 PEP 366说明了更改。
更新:根据Nick Coghlan的建议,推荐的替代方法是使用-m开关运行软件包中的模块。
回答
main.py setup.py app/ -> __init__.py package_a/ -> __init__.py module_a.py package_b/ -> __init__.py module_b.py
- 我们运行
python main.py
。 - main.py可以执行以下操作:import app.package_a.module_a`
module_a.py
确实导入app.package_b.module_b
另外2或者3可以使用:from app.package_a import module_a
只要我们在PYTHONPATH中具有" app",它就可以工作。 main.py可能在那时的任何地方。
因此,我们编写了一个" setup.py"来将整个应用程序包和子包复制(安装)到目标系统的python文件夹中,并将" main.py"复制到目标系统的脚本文件夹中。
回答
def import_path(fullpath): """ Import a file with full path specification. Allows one to import from anywhere, something __import__ does not do. """ path, filename = os.path.split(fullpath) filename, ext = os.path.splitext(filename) sys.path.append(path) module = __import__(filename) reload(module) # Might be out of date del sys.path[-1] return module
我正在使用此代码片段从路径导入模块,希望对我们有所帮助