从不同工作目录导入Python模块

31 投票
7 回答
75305 浏览
提问于 2025-04-15 12:30

我有一个Python脚本,它使用了一些内置模块,同时也导入了一些自定义模块,这些模块和主脚本在同一个文件夹里。

比如,我会这样调用:

python agent.py

而agent.py里有很多导入,包括:

import checks

其中checks是在和agent.py同一个文件夹里的一个文件。

agent/agent.py
agent/checks.py

当当前工作目录是agent/时,一切都正常。但是,如果我从其他目录调用agent.py,它就无法导入checks.py,结果就会出错。

我该怎么做才能确保无论从哪个地方调用agent.py,都能成功导入这些自定义模块呢?例如:

python /home/bob/scripts/agent/agent.py

7 个回答

7

你需要把当前正在执行的模块的路径添加到 sys.path 这个变量里。因为你是在命令行中调用它的,所以脚本的路径总是会在 sys.argv[0] 里。

import sys
import os
sys.path.append(os.path.split(sys.argv[0])[0])

现在,当你导入模块时,它也会在存放 agent.py 文件的文件夹里查找。

12

你不需要去调整 sys.path。 引用一下 Python 2.6 的文档关于 sys.path 的内容:

在程序启动时,这个列表的第一个项目,path[0],是包含用来启动 Python 解释器的脚本的目录。如果脚本目录不可用(比如说,如果你是通过交互方式启动解释器,或者脚本是从标准输入读取的),那么 path[0] 就是一个空字符串,这样 Python 会优先在当前目录中查找模块。注意,脚本目录会在 PYTHONPATH 结果插入的条目之前。

=== amod.py ===
def whoami():
    return __file__

=== ascript.py ===
import sys
print "sys.argv", sys.argv
print "sys.path", sys.path
import amod
print "amod __file__", amod.whoami()

=== result of running ascript.py from afar ===
C:\somewhere_else>\python26\python \junk\timport\ascript.py
sys.argv ['\\junk\\timport\\ascript.py']
sys.path ['C:\\junk\\timport', 'C:\\WINDOWS\\system32\\python26.zip', SNIP]
amod __file__ C:\junk\timport\amod.py

如果重新运行,最后一行当然会变成 ...amod.pyc。这并不是新鲜事,它在 Python 2.1 和 1.5.2 中也能工作。

给你一些调试提示:试试像我那样的两个简单文件。用 -v 和 -vv 参数运行 Python。把你失败测试的结果,包括完整的错误追踪和错误信息,还有你的两个文件,展示给我们。告诉我们你使用的平台和 Python 的版本。检查一下 checks.py 文件的权限。有没有其他的 checks.something_else 文件在干扰?

31

其实你的例子之所以能工作,是因为checks.py和agent.py在同一个文件夹里。但是如果checks.py在上一级文件夹,比如说:

agent/agent.py
checks.py

那么你可以这样做:

path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if not path in sys.path:
    sys.path.insert(1, path)
del path

注意这里用了__file__这个东西。

撰写回答