如何导入具有相对路径的脚本?

问题描述 投票:0回答:2

我具有以下目录结构

   project/
        bin/
            script
        stuff/
            __init__.py
            mainfile.py

在脚本内部,我具有以下启用命令行执行的功能:

#!/usr/bin/env python
from stuff import mainfile

此方法有效,但我原本希望需要跳到更高的水平...

from ..stuff import mainfile

from project.stuff import mainfile

我在这里想念什么?

python import relative-path
2个回答
0
投票

实际上,您的所有示例都不应该立即可用。

让我们稍微修改bin/script.py

#! /usr/bin/env python

import sys
print sys.path

from stuff import mainfile

这应该会产生类似的结果

['.../project/bin', ...]
Traceback (most recent call last):
  File "bin/script.py", line 6, in <module>
    from stuff import mainfile
ImportError: No module named stuff

the directory of the script(不是当前目录)自动添加到sys.path

在程序启动时初始化,此列表的第一项path[0]是包含用于调用Python解释器的脚本的目录。*如果脚本目录不可用(例如,如果解释器是交互调用的,或者如果从标准输入中读取脚本,则path[0]是空字符串,它将Python引导到首先在当前目录中搜索模块。注意,由于PYTHONPATH的结果,在插入条目之前插入了脚本目录。

因此stuff上没有sys.path模块。我不确定您的环境设置如何,但这是没有设置其他参数(例如PYTHONPATH)时的典型结果。

Similally,

from ..stuff import mainfile

将产生经典的ValueError: Attempted relative import in non-package。您将得知,您只能相对于实际模块进行相对导入。由于script内部..没有引用模块(可以说脚本本身是顶级模块),因此相对导入在这里不起作用。从Python的角度来说,脚本上方没有模块,因此..在脚本的上下文中使用时未指的是有形的东西。

注意,这还意味着not

通过删除project标记文件仅使project/bin__init__.py成为模块本身是有帮助的。仅当脚本的父级实际上是python所理解的东西时,才可能相对导入到脚本的parent

这是原因,为什么存在-m命令行开关,因此可以从命令行运行模块。例如,鉴于上述相对导入

python -m project.bin.script

有技巧,但仅当从正确的目录(projectdir

/ ..)执行时才可以。

该问题甚至更严重

from project.stuff import mainfile

因为当从project上方的目录中启动脚本时,sys.path目录仅在project上自动存在,因此[不指定要运行的主脚本:

cd <projectdir>/.. python -m project.bin.script # works cd <projectdir> python -m bin.script # does not work, because `sys.path` starts with <projectdir> # and it's `stuff.mainfile` now, not `project.stuff.mainfile`.
如果要从脚本中的project导入模块,请根据需要修复sys.path

import sys import os sys.path.insert(0, os.path.dirname(sys.path[0])) from stuff import mainfile

您需要先将父目录添加到sys.path。尝试以下操作:

# This is a file in bin/ directory. this_file_path = os.path.dirname(__file__) sys.path.append(os.path.join(this_file_path, '..')) import stuff.mainfile


0
投票
您需要先将父目录添加到sys.path。尝试以下操作:
© www.soinside.com 2019 - 2024. All rights reserved.