假设我有一个脚本集合,为方便起见,它被组织在如下目录结构中:
root
│ helpers.py
│
├───dir_a
│ data.txt
│ foo.py
│
└───dir_b
data.txt
bar.py
foo.py
和bar.py
是做不同事情的脚本,但是它们加载不同data.txt
的方式是相同的,为了避免重复,我希望在helpers.py
中放置一个load_data()
函数,当运行子目录dir_a
和dir_b
中的脚本时可以导入该函数。
我尝试过在**dir_a/foo.py
**中使用如下相对导入来导入helper:
from ..helpers import load_data
foo_data = load_data('data.txt')
# ...rest of code...
但是直接将**foo.py
**作为脚本运行会在第1行失败,并显示ImportError
:
Traceback (most recent call last):
File "path/to/file/foo.py", line 1, in <module>
from ..helpers import load_data
ImportError: attempted relative import with no known parent package
我所尝试的精神在python中是否可行(即简单且无需修改sys.path
)?来自 * 案例3:从Parent Directory * on this site导入,答案似乎是否定的,我需要重新构造我的脚本集合,以避免向上导入一个级别。
附加问题:如果不可能,理由是什么?
3条答案
按热度按时间vwkv1x7d1#
如果你在根目录下创建一个空的
__init__.py
(这会把根目录变成一个包),然后像这样调用你的foo.py
脚本:python -m root.dir_a.foo
我认为,只要您从“root”上面调用它,它就应该工作。我刚刚在我的计算机上尝试了类似的操作,它工作正常。
或者,因为您现在已经将'root'设置为包,所以您可以:
from root import helpers
当然,我假设你的根目录实际上并不叫'root',在这种情况下你应该适当地修改它。我还假设你使用的是Python3 --它在Python 2.7中不起作用。
至于为什么不把root作为一个包就不可能做到这一点,我认为这个想法是你的代码应该是位置不可知的。换句话说,你不应该依赖于你的foo.py知道它在系统中的位置。我不是Maven,但实际上可能foo.py * 不 * 知道这一点,在这种情况下,它没有办法解析
../helpers
。holgip5t2#
运行python脚本的正确方法是从根包的父目录运行,正如@JoeTodd在answer中建议的那样。如果直接从它的位置运行脚本,那么它无法知道它在一个包中,因此会出现错误(no known parent package)。
现在对于data.txt,python在给出一个相对路径时必须将其解析为一个绝对路径--它不能打开'data.txt',它需要打开c:/path/to/data.txt。因此相对路径连接到当前工作目录,默认情况下,该目录是脚本运行的目录(它也被添加到sys.path中,因此其中的包被解析)。因此,当您从root的父目录运行时,python会查找不存在的
c:/.../parent dir of root/data.txt
。正确的解决方案是 * 不 * 使用相对路径--所以:zi8p0yeb3#
将以下行添加到www.example.com脚本的顶部foo.py,
这将设置一个更高级别的模块的路径。然后,您将能够在www.example.com脚本中执行导入foo.py,如下所示:
我被一个非常相似的问题卡住了,发现这是解决这个问题的最简单的方法