我有一个使用内置模块的Python脚本,但也导入了与主脚本本身位于同一目录中的许多自定义模块。
例如,我会打电话给
python agent.py
和agent.py有许多导入,包括:
import checks
其中检查位于与agent.py
相同的目录中的文件中agent/agent.py
agent/checks.py
当前工作目录是代理/然后一切都很好。但是,如果我从任何其他目录调用agent.py,显然无法导入checks.py等错误。
我可以确保无论在何处调用agent.py,都可以导入自定义模块。
python /home/bob/scripts/agent/agent.py
答案 0 :(得分:30)
实际上你的例子是有效的,因为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__
。
答案 1 :(得分:12)
你不应该使用sys.path。引用sys.path的Python 2.6文档:
在程序启动时初始化,此列表的第一项, 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?
答案 2 :(得分:7)
您需要将当前正在执行的模块的路径添加到sys.path变量中。由于您在命令行上调用它,因此脚本的路径将始终位于sys.argv [0]中。
import sys
import os
sys.path.append(os.path.split(sys.argv[0])[0])
现在,当导入搜索模块时,它还会查找托管agent.py文件的文件夹。
答案 3 :(得分:5)
有几种方法可以向PYTHONPATH
添加内容。
阅读http://docs.python.org/library/site.html
在运行脚本之前设置PYTHONPATH
环境变量。
您可以执行此操作python -m agent
从agent.py
运行PYTHONPATH
。
在.pth
目录中创建lib/site-packages
个文件。
在lib/site-packages
。
答案 4 :(得分:1)
我认为您应该考虑将代理目录放入正确的Python包中。然后将此包放在python路径的任何位置,您可以将检查导入为
from agent import checks
答案 5 :(得分:1)
如果您知道check.py的完整路径,请使用此配方(http://code.activestate.com/recipes/159571/)
如果要将目录添加到系统路径 - 此配方(http://code.activestate.com/recipes/52662/)。在这种情况下,我必须确定应用程序目录(sys.argv [0])将此值传递给AddSysPath函数。如果你想查看生产样本,请在这个帖子上发表评论,以便我稍后发布。
问候。
答案 6 :(得分:1)
为了概括我对您的目标的理解,您希望能够使用import custom_package_name
导入自定义包,无论您从哪里调用python,无论您的python脚本位于何处。
许多答案都提到了我要描述的内容,但我觉得大多数答案都假设了很多以前的知识。我会尽量明确表达。
为了实现允许通过import
语句导入自定义程序包的目标,必须通过python用于搜索程序包的路径在某处发现它们。 Python实际上使用多个路径,但我们只关注通过将sys.prefix
(在您的python解释器中)的输出与/lib/pythonX.Y/site-packages
(或lib/site-packages
组合而找到的路径。如果您正在使用Windows,其中XY是您的python版本。
具体来说,通过运行:
找到python使用的路径import sys
your_path = sys.prefix + '/lib/pythonX.Y/site-packages'
print(your_path)
如果您使用的是python 3.5,此路径应该类似于/usr/local/lib/python3.5/site-packages
,但根据您的设置,它可能会有很大差异。
Python使用此路径(以及其他一些路径)来查找要导入的包。因此,您可以将自定义包放在/usr/local/lib/python3.5/site-packages
文件夹中。别忘了在文件夹中添加 init .py文件。
再次具体,在终端类型:
cd your_path
cp path_to_custom_package/custom_package ./
现在您应该可以导入自定义程序包的所有内容,就像程序包位于同一目录中一样(例如import package.subpackage
,程序包中的每个子程序包文件都应该有效。)