导入不在路径上的python模块
Posted
技术标签:
【中文标题】导入不在路径上的python模块【英文标题】:Import python module NOT on path 【发布时间】:2012-04-27 01:00:05 【问题描述】:我有一个模块 foo,包含 util.py 和 bar.py。
我想在 IDLE 或 python 会话中导入它。我该怎么办?
我找不到关于如何导入不在当前目录或默认 python PATH 中的模块的文档。
尝试import "<full path>/foo/util.py"
后,
和from "<full path>" import util
我能得到的最接近的是
import imp
imp.load_source('foo.util','C:/.../dir/dir2/foo')
这给了我在 Windows 7 上被拒绝的权限。
【问题讨论】:
也值得一试related question。我特别喜欢那里的top answer,因为它清楚地说明了对sys.path
进行更改的安全性。
How to import a module given the full path?的可能重复
【参考方案1】:
一种方法是简单地修改你的path:
import sys
sys.path.append('C:/full/path')
from foo import util,bar
请注意,这要求 foo 是一个 python 包,即包含一个__init__.py
文件。如果不想修改sys.path
,可以also modify the PYTHONPATH
environment variable或install the module on your system。请注意,这意味着该目录中的其他目录或.py
文件可能会被无意中加载。
因此,您可能希望改用imp.load_source
。它需要文件名,而不是目录(当前用户可以读取的文件):
import imp
util = imp.load_source('util', 'C:/full/path/foo/util.py')
【讨论】:
它可以工作,但现在当尝试通过使用方法来使用 util.method 时,它说“方法”未定义。但我可以通过 util.method 使用它。为什么? 因为你还没有定义method
,只有“util
中的method
”。您可以根据需要定义method = util.method
。
请注意,from foo import *
是糟糕的编码,除非您只是在 shell 中乱搞。
@Wooble 更正为 package。 __init__.py
是必需的。观察mkdir foo; touch foo/util.py; python -c 'from foo import util'
和touch foo/__init__.py; python -c 'from foo import util'
@EMS Python 文档explicitly mentions sys.path
。如果用户无法修改sys.path
,则极有可能imp
模块也被阻止(注意Python 的sys.path
与system's PATH
没有任何关系)。就个人而言,我不认为按名称而不是文件名加载模块是愚蠢的。它允许在系统范围内安装 Python 包(例如,在 2.5 上,您可能希望提供替代的 json
模块)。添加了警告说明。【参考方案2】:
您可以使用PYTHONPATH
环境变量自定义模块搜索路径,或手动修改sys.path
目录列表。
请参阅 python.org 上的 Module Search Path 文档。
【讨论】:
【参考方案3】:试试这个
import sys
sys.path.append('c:/.../dir/dir2')
import foo
【讨论】:
-1 因为附加到 Python 路径是一个不好的解决方案。它可以工作,但它比 imp.load_source 更糟糕,因为用户可能不想修改任何系统路径,或者可能在她或他不能这样做的计算机上工作。这实际上是 Python 中最令人讨厌的“功能”之一,否则它是一种优雅的语言。你不能只给导入一个字符串来命名另一个 .py 文件的路径,这很愚蠢。鉴于您不能,使用 imp 防止更改系统路径会更好。 @EMS 啊..我明白你在说什么,我以前没有意识到,但现在你的意思很清楚了。感谢您指出了这一点。 (我现在可能不得不修改一些我自己的代码:) 别担心。这是sys.path
的预期目的(或至少一个预期的用例)。 F先生(显然以前是EMS)错了。正如 phihag 在对他的回答中相同的 -1 评论的回复中指出的那样,sys.path
与整个系统路径不相关。
@ely 在 python3.3 之后似乎不推荐使用 imp.load_source (load_module) 有什么替代方案?
导入 foo 后,如果您担心会弄乱其他导入,请执行 sys.path.pop()。【参考方案4】:
按照 phihag 的提示,我有这个解决方案。只需将源文件的路径提供给load_src
,它就会加载它。您还必须提供一个名称,以便您可以使用此名称导入此模块。我更喜欢这样做,因为它更明确:
def load_src(name, fpath):
import os, imp
return imp.load_source(name, os.path.join(os.path.dirname(__file__), fpath))
load_src("util", "../util.py")
import util
print util.method()
另一种(不太明确的)方式是这样的:
util = load_src("util", "../util.py") # "import util" is implied here
print util.method() # works, util was imported by the previous line
编辑:方法被重写以使其更清晰。
【讨论】:
以上是关于导入不在路径上的python模块的主要内容,如果未能解决你的问题,请参考以下文章