导入不在路径上的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模块的主要内容,如果未能解决你的问题,请参考以下文章

如何在python3中正确导入同一目录下的模块

如何在python3中正确导入同一目录下的模块

python学习手册:第二十二章——模块代码编写基础

Python导入模块的方法

Python找不到自定义的模块

python 搜索路径顺序查找