Import python module NOT on path
我有一个模块foo,包含util.py和bar.py。
我想在空闲或Python会话中导入它。我该怎么办?
我找不到有关如何导入不在当前目录或默认python路径中的模块的文档。在尝试过import"/foo/util.py"之后,和from"" import util。
我能得到的最接近的是
1 2
| import imp
imp.load_source('foo.util','C:/.../dir/dir2/foo') |
这给了我在Windows7上被拒绝的许可。
- 同样值得一看这个相关的问题。特别是,我喜欢上面的答案,因为它清楚地说明了sys.path变更的安全性。
- 如何导入给定完整路径的模块的可能副本?
一种方法是简单地修改你的路径:
1 2 3
| import sys
sys.path.append('C:/full/path')
from foo import util,bar |
注意,这要求foo是一个python包,即包含一个__init__.py文件。如果不想修改sys.path,也可以修改PYTHONPATH环境变量或在系统上安装模块。注意,这意味着该目录中的其他目录或.py文件可能会意外加载。
因此,您可能希望使用imp.load_source。它需要文件名,而不是目录(当前用户可以读取的文件):
1 2
| import imp
util = imp.load_source('util', 'C:/full/path/foo/util.py') |
- 它可以工作,但现在当尝试通过方法使用util.method时,它说"method"未定义。但我可以通过util.method使用它。为什么?
- 因为您没有定义method,所以只有"util中的method"。如果需要,可以定义method = util.method。
- 注意,除非您只是在shell中进行黑客攻击,否则from foo import *是一种糟糕的编码。
- @KatrielAlex谢谢。我使用的是来自foo import util,而不是来自foo import*。所以别担心;)
- @旋涡3x好,这使得util在您的名称空间中可用。为什么您希望以method的名义提供util.method?这意味着你必须确保在bar中没有另一个method,从而击败模块系统的整个点,即不必担心名称冲突。
- @phihag因为我对python不熟悉,所以我知道它现在是如何工作的:)
- @Wooble改为套装。需要__init__.py。观察mkdir foo; touch foo/util.py; python -c 'from foo import util'和touch foo/__init__.py; python -c 'from foo import util'。
- -1,因为附加到python路径是一个错误的解决方案。它可以工作,但严格来说比imp.load_source更糟,因为用户可能不想修改任何系统路径,或者可能正在无法修改的计算机上工作。这实际上是Python中最令人讨厌的"特性"之一,否则它就是一种优雅的语言。你不能给import一个字符串来命名另一个.py文件的路径,这太愚蠢了。如果您不能,那么使用imp来防止系统路径发生变化就更好了。
- @ems python文档明确提到sys.path。如果用户不能修改sys.path,那么很可能imp模块也被阻塞了(注意python的sys.path与系统的PATH无关)。就个人而言,我不认为用名称而不是文件名来加载模块是愚蠢的;它允许在系统范围内安装python包(例如,在2.5版上,您可能希望为您的可选json模块提供服务)。添加了一个警告注释。
- 好吧,是的,从一个包中导入确实需要__init__.py,尽管如果没有它,/foo被添加到sys.path,那么import util和import bar都可以工作。(投票改为+1)
您可以使用PYTHONPATH环境变量自定义模块搜索路径,或者手动修改sys.path目录列表。
请参见python.org上的模块搜索路径文档。
试一试
1 2 3
| import sys
sys.path.append('c:/.../dir/dir2')
import foo |
- -1,因为附加到python路径是一个错误的解决方案。它可以工作,但是它比imp.load_source更糟糕,因为用户可能不想修改任何系统路径,或者可能在无法修改的计算机上工作。这实际上是Python中最令人讨厌的"特性"之一,否则它就是一种优雅的语言。你不能给import一个字符串来命名另一个.py文件的路径,这很愚蠢。如果您不能,那么使用IMP来防止系统路径发生变化就更好了。
- 嗯…我知道你在说什么,我以前没有意识到,但现在你说的话已经很清楚了。谢谢你指出这一点。(我现在可能需要修改一些自己的代码:)
- 别担心。这是sys.path的预期用途(或至少是预期的用例)。F先生(显然以前是EMS)是错的。正如phihag在对他答案的相同-1评论的回复中指出的,sys.path与整个系统路径无关。
- @伊利看来,在python3.3之后,imp.load_source(load_module)已经被弃用了。还有什么可以替代的呢?
根据Phihag的提示,我有这个解决方案。只需将源文件的路径提供给load_src,它就会加载它。您还必须提供一个名称,以便可以使用此名称导入此模块。我更喜欢这样做,因为它更明确:
1 2 3 4 5 6 7 8
| 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() |
另一种(不太明确)方法是:
1 2 3
| util = load_src("util","../util.py") #"import util" is implied here
print util.method() # works, util was imported by the previous line |
编辑:重写方法使其更清晰。