从不同工作目录导入Python模块
我有一个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 个回答
你需要把当前正在执行的模块的路径添加到 sys.path 这个变量里。因为你是在命令行中调用它的,所以脚本的路径总是会在 sys.argv[0] 里。
import sys
import os
sys.path.append(os.path.split(sys.argv[0])[0])
现在,当你导入模块时,它也会在存放 agent.py 文件的文件夹里查找。
你不需要去调整 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 文件在干扰?
其实你的例子之所以能工作,是因为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__
这个东西。