想象一下这个目录结构: python
app/ __init__.py sub1/ __init__.py mod1.py sub2/ __init__.py mod2.py
我正在编码mod1
,我须要从mod2
导入一些东西。 我该怎么办? app
我尝试from ..sub2 import mod2
尝试from ..sub2 import mod2
但出现“未打包的相对尝试导入”。 测试
我四处搜寻,但只发现“ sys.path
操纵”黑客。 有没有一种干净的方法? 编码
编辑:我全部的__init__.py
当前为空 spa
Edit2:我正在尝试执行此操做,由于sub2包含跨子包( sub1
, subX
等)共享的类。 code
Edit3:我要寻找的行为与PEP 366中描述的相同(感谢John B) ip
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
我正在使用此代码片断从路径导入模块,但愿对您有所帮助 ci
除了John B所说的之外,设置__package__
变量彷佛应该有所帮助,而不是更改__main__
可能会搞砸其余事情。 可是据我测试,它并不能彻底正常工做。 字符串
我遇到了一样的问题,而据我所知,PEP 328或366都没法彻底解决问题,由于二者在一天结束时都须要将程序包的头包含在sys.path
。 get
我还要提到的是,我没有找到如何格式化应放入这些变量的字符串的格式。 是"package_head.subfolder.module_name"
仍是什么?
让我将其放在此处以供我本身参考。 我知道这不是很好的Python代码,可是我须要一个脚原本处理我正在从事的项目,因此我想将该脚本放在scripts
目录中。
import os.path import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
这是对我有效的解决方案:
我from ..sub2 import mod2
进行相对from ..sub2 import mod2
,而后,若是我想运行mod1.py
则转到app
的父目录,并使用python -m开关做为python -m app.sub1.mod1
运行模块python -m app.sub1.mod1
相对导入发生此问题的真正缘由是,相对导入经过采用模块的__name__
属性__name__
。 若是模块直接运行,则__name__
设置为__main__
,而且不包含有关包结构的任何信息。 而且,这就是为何python抱怨relative import in non-package
错误中的relative import in non-package
。
所以,经过使用-m开关,您能够将包结构信息提供给python,经过它能够成功解析相对导入。
在进行相对导入时,我屡次遇到此问题。 并且,在阅读了全部先前的答案以后,我仍然没法弄清楚如何解决此问题,而无需在全部文件中都放入样板代码。 (尽管有些评论确实颇有帮助,这要感谢@ncoghlan和@XiongChiamiov)
但愿这对正在解决相对进口问题的人有所帮助,由于经过PEP确实颇有趣。
用示例解释nosklo's
答案
注意:全部__init__.py
文件均为空。
main.py app/ -> __init__.py package_a/ -> __init__.py fun_a.py package_b/ -> __init__.py fun_b.py
def print_a(): print 'This is a function in dir package_a'
from app.package_a.fun_a import print_a def print_b(): print 'This is a function in dir package_b' print 'going to call a function in dir package_a' print '-'*30 print_a()
from app.package_b import fun_b fun_b.print_b()
若是运行$ python main.py
它将返回:
This is a function in dir package_b going to call a function in dir package_a ------------------------------ This is a function in dir package_a
from app.package_b import fun_b
from app.package_a.fun_a import print_a
所以,文件夹package_b
中的文件使用了文件夹package_a
中的文件,这就是您想要的。 对??