How to import a module given the full path?
如何在给定完整路径的情况下加载Python模块?请注意,该文件可以在文件系统中的任何位置,因为它是一个配置选项。
对于python 3.5+使用:
1 2 3 4 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,请使用:
1 2 3 4 | from importlib.machinery import SourceFileLoader foo = SourceFileLoader("module.name","/path/to/file.py").load_module() foo.MyClass() |
(尽管在python 3.4中已经弃用了这种方法。)
Python 2用途:
1 2 3 4 | import imp foo = imp.load_source('module.name', '/path/to/file.py') foo.MyClass() |
编译后的python文件和dll有相同的方便函数。
请参见。http://bugs.python.org/issue21436。
向sys.path添加路径(而不是使用imp)的好处是,当从单个包导入多个模块时,它简化了操作。例如:
1 2 3 4 5 6 7 | 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 |
听起来您不想专门导入配置文件(这涉及到很多副作用和额外的复杂性),您只想运行它,并且能够访问产生的名称空间。标准库以runpy.run_路径的形式专门提供了一个API:
1 2 | from runpy import run_path settings = run_path("/path/to/file.py") |
该接口在python 2.7和python 3.2中可用。+
您也可以这样做,并将配置文件所在的目录添加到python加载路径中,然后进行常规导入,假设您事先知道文件名,在本例中为"config"。
乱七八糟的,但它起作用了。
1 2 3 4 5 6 7 8 | configfile = '~/config.py' import os import sys sys.path.append(os.path.dirname(os.path.expanduser(configfile))) import config |
你可以使用
1 | load_source(module_name, path_to_file) |
来自IMP模块的方法。
我想出了一个稍微修改过的@sebastianrittau的绝妙答案(我认为对于python>3.4),它允许您使用
1 2 3 4 5 6 | 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) |
在显式
你是说载入还是导入?
您可以操作sys.path列表,指定模块的路径,然后导入模块。例如,给定一个模块:
1 | /foo/bar.py |
你可以这样做:
1 2 3 | import sys sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path import bar |
下面是一些适用于所有Python版本的代码,从2.7到3.5,甚至可能是其他版本。
1 2 3 4 | config_file ="/tmp/config.py" with open(config_file) as f: code = compile(f.read(), config_file, 'exec') exec(code, globals(), locals()) |
我测试了它。它可能很难看,但到目前为止,它是唯一适用于所有版本的版本。
如果您的顶级模块不是一个文件,而是打包为一个目录,其中包含uuinit_uuuuy.py,那么接受的解决方案几乎可以工作,但不完全可以工作。在python 3.5+中,需要以下代码(注意以"sys.modules"开头的添加行):
1 2 3 4 5 6 7 8 | 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_模块时,它会尝试将顶级uuu in it_uuu.py中的相对导入绑定到顶级模块名称,在本例中是"mymodule"。但"mymodule"尚未加载,因此会出现错误"systemError:父模块"mymodule"未加载,无法执行相对导入"。所以在加载之前需要绑定名称。原因是相对导入系统的基本不变量:"不变量保留是,如果您有sys.modules['spam']和sys.modules['spam.foo'](正如您在上述导入之后所做的那样),后者必须显示为前者的foo属性",如本文所述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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') |
要导入模块,需要将其目录临时或永久地添加到环境变量中。
暂时地1 2 3 | import sys sys.path.append("/path/to/my/modules/") import my_module |
永久地
将以下行添加到您的
1 | export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/" |
信贷/来源:Saarrr,另一个StackExchange问题
我相信您可以使用
1 | imp.find_module('mymodule', '/home/mypath/') |
…但这应该能完成任务。
python 3.4的这一部分似乎是极其曲折的理解!然而,在使用ChrisCalloway的代码进行了一些黑客攻击之后,我设法找到了一些有用的东西。这是基本功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | def import_module_from_file(full_path_to_module): """ Import a module given the full path/filename of the .py file Python 3.4 """ module = None try: # Get module name and path from full path module_dir, module_file = os.path.split(full_path_to_module) module_name, module_ext = os.path.splitext(module_file) # Get module"spec" from filename spec = importlib.util.spec_from_file_location(module_name,full_path_to_module) module = spec.loader.load_module() except Exception as ec: # Simple error printing # Insert"sophisticated" stuff here print(ec) finally: return module |
这似乎使用了Python3.4中不推荐使用的模块。我不想假装理解为什么,但它似乎在程序中起作用。我发现Chris的解决方案在命令行上有效,但不是在程序内部。
我并不是说它更好,但为了完整性,我想建议使用在python 2和3中都可用的
例如,如果您在
1 2 3 4 | module = dict() with open("/path/to/module") as f: exec(f.read(), module) module['foo']() |
这使得动态加载代码更加明确,并授予您一些额外的能力,例如提供自定义内置的能力。
如果通过属性访问,而不是通过键访问对您很重要,您可以为全局变量设计一个自定义dict类,它提供了这样的访问,例如:
1 2 3 | class MyModuleClass(dict): def __getattr__(self, name): return self.__getitem__(name) |
创建python模块test.py
1 2 3 4 5 | import sys sys.path.append("<project-path>/lib/") from tes1 import Client1 from tes2 import Client2 import tes3 |
创建python模块test_check.py
1 2 3 | from test import Client1 from test import Client2 from test import test3 |
我们可以从模块导入导入模块。
您可以使用
1 2 3 4 5 6 7 | import pkgutil import importlib packages = pkgutil.walk_packages(path='.') for importer, name, is_package in packages: mod = importlib.import_module(name) # do whatever you want with module now, it's been imported! |
这应该管用
1 2 3 4 5 6 7 | path = os.path.join('./path/to/folder/with/py/files', '*.py') for infile in glob.glob(path): basename = os.path.basename(infile) basename_without_extension = basename[:-3] # http://docs.python.org/library/imp.html?highlight=imp#module-imp imp.load_source(basename_without_extension, infile) |
要从给定文件名导入模块,可以临时扩展路径,并在finally块引用中恢复系统路径:
1 2 3 4 5 6 7 8 9 10 11 | filename ="directory/module.py" directory, module_name = os.path.split(filename) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) finally: sys.path[:] = path # restore |
运行时导入包模块(python配方)
http://code.activestate.com/recipes/223972/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | ################### ## # ## classloader.py # ## # ################### import sys, types def _get_mod(modulePath): try: aMod = sys.modules[modulePath] if not isinstance(aMod, types.ModuleType): raise KeyError except KeyError: # The last [''] is very important! aMod = __import__(modulePath, globals(), locals(), ['']) sys.modules[modulePath] = aMod return aMod def _get_func(fullFuncName): """Retrieve a function object from a full dotted-package name.""" # Parse out the path, module, and function lastDot = fullFuncName.rfind(u".") funcName = fullFuncName[lastDot + 1:] modPath = fullFuncName[:lastDot] aMod = _get_mod(modPath) aFunc = getattr(aMod, funcName) # Assert that the function is a *callable* attribute. assert callable(aFunc), u"%s is not callable." % fullFuncName # Return a reference to the function itself, # not the results of the function. return aFunc def _get_class(fullClassName, parentClass=None): """Load a module and retrieve a class (NOT an instance). If the parentClass is supplied, className must be of parentClass or a subclass of parentClass (or None is returned). """ aClass = _get_func(fullClassName) # Assert that the class is a subclass of parentClass. if parentClass is not None: if not issubclass(aClass, parentClass): raise TypeError(u"%s is not a subclass of %s" % (fullClassName, parentClass)) # Return a reference to the class itself, not an instantiated object. return aClass ###################### ## Usage ## ###################### class StorageManager: pass class StorageManagerMySQL(StorageManager): pass def storage_object(aFullClassName, allOptions={}): aStoreClass = _get_class(aFullClassName, StorageManager) return aStoreClass(allOptions) |
我为你做了一个使用
1 2 3 | >>>from import_file import import_file >>>mylib = import_file('c:\\mylib.py') >>>another = import_file('relative_subdir/another.py') |
您可以在以下网址获得:
http://pypi.python.org/pypi/import_文件
或AT
http://code.google.com/p/import-file(导入文件)/
在Linux中,在python脚本所在的目录中添加符号链接是可行的。
IE:
1 | ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py |
python将创建
然后在mypythonscript.py中包含以下内容
1 | from module import * |
非常简单的方法:假设您希望导入具有相对路径../../mylibs/pyfunc.py的文件。
1 2 3 4 | libPath = '../../MyLibs' import sys if not libPath in sys.path: sys.path.append(libPath) import pyfunc as pf |
但如果你没有警卫,你最终会走上一条很长的路。
使用
1 2 3 4 5 6 | import importlib dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py' sys.path.append(dirname) # only directories should be added to PYTHONPATH module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule' module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for"module_name") |
现在可以直接使用导入模块的名称空间,如下所示:
1 2 | a = module.myvar b = module.myfunc(a) |
这个解决方案的优点是,为了在代码中使用它,我们甚至不需要知道要导入的模块的实际名称。这很有用,例如,在模块路径是可配置参数的情况下。
因为我找不到任何有效的答案,所以将此添加到答案列表中。这将允许在3.4中导入编译的(pyd)python模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import sys import importlib.machinery def load_module(name, filename): # If the Loader finds the module name in this list it will use # module_name.__file__ instead so we need to delete it here if name in sys.modules: del sys.modules[name] loader = importlib.machinery.ExtensionFileLoader(name, filename) module = loader.load_module() locals()[name] = module globals()[name] = module load_module('something', r'C:\Path\To\something.pyd') something.do_something() |
这个答案是对塞巴斯蒂安·里陶回答评论的补充:"但是如果你没有模块名呢?"这是一种快速而肮脏的方法,可以将可能的python模块名命名为一个文件名——它只是在树上查找一个没有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import pathlib def likely_python_module(filename): ''' Given a filename or Path, return the"likely" python module name. That is, iterate the parent directories until it doesn't contain an __init__.py file. :rtype: str ''' p = pathlib.Path(filename).resolve() paths = [] if p.name != '__init__.py': paths.append(p.stem) while True: p = p.parent if not p: break if not p.is_dir(): break inits = [f for f in p.iterdir() if f.name == '__init__.py'] if not inits: break paths.append(p.stem) return '.'.join(reversed(paths)) |
当然有改进的可能性,可选的
我认为,最好的办法是从官方文件(29.1.IMP-访问导入内部):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import imp import sys def __import__(name, globals=None, locals=None, fromlist=None): # Fast path: see if the module has already been imported. try: return sys.modules[name] except KeyError: pass # If any of the following calls raises an exception, # there's a problem we can't handle -- let the caller handle it. fp, pathname, description = imp.find_module(name) try: return imp.load_module(name, fp, pathname, description) finally: # Since we may exit via an exception, close fp explicitly. if fp: fp.close() |