如何在完整路径下加载Python模块?请注意,该文件可以位于文件系统中的任何位置,因为它是一个配置选项.
对于Python 3.5+使用:
import importlib.util spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") foo = importlib.util.module_from_spec(spec) spec.loader.exec_module(foo) foo.MyClass()
对于Python 3.3和3.4使用:
from importlib.machinery import SourceFileLoader foo = SourceFileLoader("module.name", "/path/to/file.py").load_module() foo.MyClass()
(虽然这在Python 3.4中已被弃用.)
Python 2使用:
import imp foo = imp.load_source('module.name', '/path/to/file.py') foo.MyClass()
编译的Python文件和DLL有相同的便利功能.
也可以看看.http://bugs.python.org/issue21436.
向sys.path添加路径(使用imp)的优点是,当从单个包导入多个模块时,它简化了操作.例如:
import sys # the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py sys.path.append('/foo/bar/mock-0.3.1') from testcase import TestCase from testutils import RunTests from mock import Mock, sentinel, patch
要导入模块,您需要临时或永久地将其目录添加到环境变量中.
暂时import sys sys.path.append("/path/to/my/modules/") import my_module永久性
.bashrc
将以下行添加到您的文件(在Linux中)并source ~/.bashrc
在终端中执行:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Credit/Source:saarrrr,另一个stackexchange 问题
如果您的顶级模块不是文件但是打包为__init__.py的目录,那么接受的解决方案几乎可以正常工作,但并不完全.在Python 3.5+中需要以下代码(请注意以'sys.modules'开头的添加行):
MODULE_PATH = "/path/to/your/module/__init__.py" MODULE_NAME = "mymodule" import importlib import sys spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH) module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module)
如果没有这一行,当执行exec_module时,它会尝试将顶级__init__.py中的相对导入绑定到顶级模块名称 - 在本例中为"mymodule".但是"mymodule"尚未加载,因此您将收到错误"SystemError:Parent module'mymodule'未加载,无法执行相对导入".因此,您需要在加载名称之前绑定该名称.原因是相对导入系统的基本不变量:"不变量持有是如果你有sys.modules ['spam']和sys.modules ['spam.foo'](正如你在上面的导入之后那样) ),后者必须作为前者的foo属性出现" 如此处所讨论的那样.
听起来你不想专门导入配置文件(它有很多副作用和涉及的额外复杂性),你只想运行它,并能够访问生成的命名空间.标准库以runpy.run_path的形式专门为其提供API :
from runpy import run_path settings = run_path("/path/to/file.py")
该接口在Python 2.7和Python 3.2+中可用
您也可以执行类似这样的操作,并将配置文件所在的目录添加到Python加载路径中,然后执行常规导入,假设您事先知道文件的名称,在本例中为"config".
凌乱,但它的确有效.
configfile = '~/config.py' import os import sys sys.path.append(os.path.dirname(os.path.expanduser(configfile))) import config
你可以使用
load_source(module_name, path_to_file)
来自imp模块的方法.
我想出了一个稍微修改过的@ SebastianRittau的精彩答案(对于我认为的Python> 3.4),这将允许您使用任何扩展名作为模块加载文件spec_from_loader
而不是spec_from_file_location
:
from importlib.util import spec_from_loader, module_from_spec from importlib.machinery import SourceFileLoader spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py")) mod = module_from_spec(spec) spec.loader.exec_module(mod)
在显式中编码路径的优点SourceFileLoader
是机器不会试图从扩展中找出文件的类型.这意味着您可以.txt
使用此方法加载类似文件的内容,但如果spec_from_file_location
没有指定加载器.txt
则无法执行此操作,因为它不在importlib.machinery.SOURCE_SUFFIXES
.
你的意思是加载还是导入?
您可以操作sys.path列表指定模块的路径,然后导入模块.例如,给定一个模块:
/foo/bar.py
你可以这样做:
import sys sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path import bar
下面是一些适用于所有Python版本的代码,从2.7-3.5甚至其他版本.
config_file = "/tmp/config.py" with open(config_file) as f: code = compile(f.read(), config_file, 'exec') exec(code, globals(), locals())
我测试了它.它可能很难看但到目前为止是唯一一个适用于所有版本的产品.
def import_file(full_path_to_module): try: import os module_dir, module_file = os.path.split(full_path_to_module) module_name, module_ext = os.path.splitext(module_file) save_cwd = os.getcwd() os.chdir(module_dir) module_obj = __import__(module_name) module_obj.__file__ = full_path_to_module globals()[module_name] = module_obj os.chdir(save_cwd) except: raise ImportError import_file('/home/somebody/somemodule.py')
我相信你可以使用imp.find_module()
和imp.load_module()
加载指定的模块.您需要将模块名称从路径中分离出来,即如果您想加载/home/mypath/mymodule.py
,则需要执行以下操作:
imp.find_module('mymodule', '/home/mypath/')
......但那应该完成工作.