首页 > 解决方案 > 在子目录中运行脚本时从上一级目录导入模块

问题描述

假设我在一个目录结构中为了方便而组织了一组脚本,如下所示:

root
│   helpers.py
│
├───dir_a
│       data.txt
│       foo.py
│
└───dir_b
        data.txt
        bar.py

foo.py并且bar.py是脚本在做不同的事情,但它们都data.txt以相同的方式加载它们的不同。为了避免重复自己,我希望load_data()helpers.py子目录dir_adir_b.

我曾尝试dir_a/foo.py使用这样的相对导入来导入助手:

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:从本网站上的父目录导入 ,答案似乎是否定的,我需要重组我的脚本集合以避免导入上一级。

额外的问题:如果不可能,为什么不这样做的理由是什么?

标签: pythonpython-3.xpython-importrelative-import

解决方案


运行 python 脚本的正确方法是从根包的父目录中,如@JoeTodd的答案中所建议的那样。如果您直接从其位置运行脚本,那么它无法知道它在包中,因此会出现错误(没有已知的父包)。

现在对于data.txt,python在给定相对路径时必须将其解析为绝对路径-它无法打开'data.txt',它需要打开c:/path/to/data.txt。因此,相对路径被连接到当前工作目录,默认情况下,该目录是运行脚本的目录(它也被添加到 sys.path 中,因此其中的包被解析)。因此,当您从 root 的父目录运行时,python 会查找c:/.../parent dir of root/data.txt不存在的目录。正确的解决方案是使用相对路径 - 所以:

path_to_data = os.path.join(os.path.dirname(__file__), 'data.txt'))
foo_data = load_data(path_to_data)

推荐阅读