导入python模块不在路径上

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 utilimport 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

编辑:重写方法使其更清晰。