如何在给定完整路径的情况下动态导入模块?

如何在给定其完整路径的情况下加载Python模块?

请注意,文件可以位于用户具有访问权限的文件系统中的任何位置。


另请参阅:如何导入一个名称为字符串的模块?

1330443 次浏览

我相信你可以使用#0#1来加载指定的模块。你需要将模块名称从路径中拆分出来,也就是说,如果你想加载/home/mypath/mymodule.py,你需要这样做:

imp.find_module('mymodule', '/home/mypath/')

…但这应该完成工作。

对于Python 3.5+使用(文档):

import importlib.utilimport sysspec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")foo = importlib.util.module_from_spec(spec)sys.modules["module.name"] = foospec.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

您可以使用

load_source(module_name, path_to_file)

方法imp模块

在运行时导入包模块(Python配方)

http://code.activestate.com/recipes/223972/

#####################                ### classloader.py ###                ####################
import sys, types
def _get_mod(modulePath):try:aMod = sys.modules[modulePath]if not isinstance(aMod, types.ModuleType):raise KeyErrorexcept KeyError:# The last [''] is very important!aMod = __import__(modulePath, globals(), locals(), [''])sys.modules[modulePath] = aModreturn aMod
def _get_func(fullFuncName):"""Retrieve a function object from a full dotted-package name."""
# Parse out the path, module, and functionlastDot = 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 parentClassor 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: passclass StorageManagerMySQL(StorageManager): pass
def storage_object(aFullClassName, allOptions={}):aStoreClass = _get_class(aFullClassName, StorageManager)return aStoreClass(allOptions)

您也可以这样做,并将配置文件所在的目录添加到Python加载路径中,然后进行正常导入,假设您事先知道文件的名称,在本例中为“config”。

很乱,但它奏效了。

configfile = '~/config.py'
import osimport sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config

你是说装载还是进口?

您可以操作sys.path列表指定模块的路径,然后导入您的模块。例如,给定一个模块:

/foo/bar.py

你可以这样做:

import syssys.path[0:0] = ['/foo'] # Puts the /foo directory at the start of your pathimport bar

你可以使用__import__chdir

def import_file(full_path_to_module):try:import osmodule_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_moduleglobals()[module_name] = module_objos.chdir(save_cwd)except Exception as e:raise ImportError(e)return module_obj

import_file('/home/somebody/somemodule.py')

向sys.path添加路径(而不是使用imp)的优点是,当从单个包导入多个模块时,它简化了事情。例如:

import sys# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.pysys.path.append('/foo/bar/mock-0.3.1')
from testcase import TestCasefrom testutils import RunTestsfrom mock import Mock, sentinel, patch

我为你做了一个使用imp的包。我称之为import_file,它是这样使用的:

>>>from import_file import import_file>>>mylib = import_file('c:\\mylib.py')>>>another = import_file('relative_subdir/another.py')

你可以得到它在:

或在

这应该能行

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-impimp.load_source(basename_without_extension, infile)

您可以使用pkgutil模块(特别是#1方法)来获取当前目录中的包列表。从那里使用importlib机制导入您想要的模块很简单:

import pkgutilimport 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!

在Linux,在Python脚本所在的目录中添加符号链接是可行的。

即:

ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py

Python解释器将创建/absolute/path/to/script/module.pyc,并在您更改/absolute/path/to/module/module.py的内容时更新它。

然后在文件mypythonscript.py中包含以下内容:

from module import *

我认为最好的方法是来自官方留档(29.1. imp-访问导入内部):

import impimport 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()

Python 3.4的这个领域似乎很难理解!然而,通过使用Chris Calloway的代码进行一些黑客攻击,我设法让一些东西发挥作用。这是基本功能。

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 pathmodule_dir, module_file = os.path.split(full_path_to_module)module_name, module_ext = os.path.splitext(module_file)
# Get module "spec" from filenamespec = 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 hereprint(ec)
finally:return module

这似乎使用了Python 3.4中不建议使用的模块。我并不假装理解为什么,但它似乎在程序中工作。我发现Chris的解决方案在命令行上工作,但不在程序内部工作。

我不是说它更好,但为了完整起见,我想建议使用#0函数,它在Python 2和Python 3中都可用。

exec允许您在全局范围内或在作为字典提供的内部范围内执行任意代码。

例如,如果您有一个存储在"/path/to/module"中的模块,其函数为foo(),您可以通过执行以下操作来运行它:

module = dict()with open("/path/to/module") as f:exec(f.read(), module)module['foo']()

这使得动态加载代码更加明确,并授予您一些额外的功能,例如提供自定义内置程序的能力。

如果通过属性而不是键进行访问对您很重要,您可以为全局变量设计一个自定义字典类,它提供这样的访问,例如:

class MyModuleClass(dict):def __getattr__(self, name):return self.__getitem__(name)

要从给定的文件名导入模块,您可以暂时扩展路径,并在最后块参考:中恢复系统路径

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

听起来你不想专门导入配置文件(这会带来很多副作用和额外的并发症)。你只想运行它,并能够访问生成的命名空间。标准库以runpy.run_path的形式专门为此提供了一个API:

from runpy import run_pathsettings = run_path("/path/to/file.py")

该接口在Python 2.7和Python 3.2+中可用。

以下是一些适用于所有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())

我测试了它。它可能很丑,但到目前为止,它是唯一一个适用于所有版本的。

我想出了@SebastianRittau精彩的回答的一个稍微修改的版本(我认为对于Python>3.4),它将允许您使用#0而不是#1作为模块加载具有任何扩展名的文件:

from importlib.util import spec_from_loader, module_from_specfrom 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)

以显式#0编码路径的优点是机械不会尝试从扩展名中找出文件的类型。这意味着您可以使用此方法加载类似于.txt文件的内容,但您不能在不指定加载程序的情况下使用spec_from_file_location来执行此操作,因为.txt不在#4中。

我在此基础上放置了一个实现,并将@SamGrondahl有用的修改放入我的实用程序库哈吉斯中。该函数称为#0。它添加了一些巧妙的技巧,例如在加载时将变量注入模块命名空间的能力。

这将允许在3.4中导入已编译(pyd)Python模块:

import sysimport 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 hereif name in sys.modules:del sys.modules[name]loader = importlib.machinery.ExtensionFileLoader(name, filename)module = loader.load_module()locals()[name] = moduleglobals()[name] = module
load_module('something', r'C:\Path\To\something.pyd')something.do_something()

一个非常简单的方法:假设你想要导入相对路径为…/… /MyLibs/pyfunc.py的文件

libPath = '../../MyLibs'import sysif not libPath in sys.path: sys.path.append(libPath)import pyfunc as pf

但是如果你在没有警卫的情况下成功了,你最终可以走很长的路。

如果你的顶级模块不是一个文件,而是被打包为一个带有__init__. py的目录,那么接受的解决方案几乎可以工作,但不完全可以。在Python 3.5+中需要以下代码(注意添加的以'sys.modules'开头的行):

MODULE_PATH = "/path/to/your/module/__init__.py"MODULE_NAME = "mymodule"import importlibimport sysspec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)module = importlib.util.module_from_spec(spec)sys.modules[spec.name] = modulespec.loader.exec_module(module)

如果没有这一行,当执行exec_module时,它会尝试将顶层__init__. py中的相对导入绑定到顶层模块名称-在本例中为“mymod”。但是“mymod”尚未加载,因此您会收到错误“SystemError:父模块'mymod'未加载,无法执行相对导入”。因此您需要在加载它之前绑定名称。原因是相对导入系统的基本不变量:“不变保持是,如果您有sys.modules['spam']和sys.modules['spam.foo'](就像您在上面的导入之后一样),后者必须显示为前者的foo属性”正如这里讨论的

使用importlib而不是imp包的简单解决方案(针对Python 2.7进行了测试,尽管它也应该适用于Python 3):

import importlib
dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'sys.path.append(dirname) # only directories should be added to PYTHONPATHmodule_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")

现在可以直接使用导入模块的命名空间,如下所示:

a = module.myvarb = module.myfunc(a)

这个解决方案的优点是我们甚至不需要知道我们想要导入的模块的实际名称,以便在我们的代码中使用它。这很有用,例如,如果模块的路径是可配置的参数。

这个答案是对Sebastian Rittau的回答回应评论的补充:“但是如果你没有模块名称怎么办?”这是一种快速而肮脏的方法,可以获得给定文件名的可能的Python模块名称——它只是向上树,直到找到一个没有__init__.py文件的目录,然后将其转换回文件名。对于Python 3.4+(使用path lib),这是有道理的,因为Python 2的人可以使用“imp”或其他方式进行相对导入:

import pathlib
def likely_python_module(filename):'''Given a filename or Path, return the "likely" python module name.  That is, iteratethe 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.parentif not p:breakif 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))

当然有改进的可能性,可选的__init__.py文件可能需要其他更改,但如果您通常有__init__.py,这就可以了。

要导入您的模块,您需要将其目录临时或永久添加到环境变量中。

暂时的

import syssys.path.append("/path/to/my/modules/")import my_module

永久

将以下行添加到Linux中的.bashrc(或替代)文件并在终端中执行source ~/.bashrc(或替代):

export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"

图片来源:saarrr另一个堆栈交换问题

创建Python模块test.py

import syssys.path.append("<project-path>/lib/")from tes1 import Client1from tes2 import Client2import tes3

创建Python模块test_check.py

from test import Client1from test import Client2from test import test3

我们可以从模块导入导入的模块。

我已经编写了自己的全局和便携式导入函数,基于importlib模块,用于:

  • 能够将两个模块作为子模块导入,并将模块的内容导入父模块(如果没有父模块,则导入全局)。
  • 能够导入文件名中带有句点字符的模块。
  • 能够导入具有任何扩展的模块。
  • 能够为子模块使用独立名称,而不是默认的不带扩展名的文件名。
  • 能够基于先前导入的模块定义导入顺序,而不是依赖于sys.path或任何搜索路径存储。

示例目录结构:

<root>|+- test.py|+- testlib.py|+- /std1|   ||   +- testlib.std1.py|+- /std2|   ||   +- testlib.std2.py|+- /std3|+- testlib.std3.py

包含依赖和顺序:

test.py-> testlib.py-> testlib.std1.py-> testlib.std2.py-> testlib.std3.py

执行:

最新更改存储:https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py

test.py

import os, sys, inspect, copy
SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("test::SOURCE_FILE: ", SOURCE_FILE)
# portable import to the global spacesys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directoryimport tacklelib as tkl
tkl.tkl_init(tkl)
# cleanupdel tkl # must be instead of `tkl = None`, otherwise the variable would be still persistsys.path.pop()
tkl_import_module(SOURCE_DIR, 'testlib.py')
print(globals().keys())
testlib.base_test()testlib.testlib_std1.std1_test()testlib.testlib_std1.testlib_std2.std2_test()#testlib.testlib.std3.std3_test()                             # does not reachable directly ...getattr(globals()['testlib'], 'testlib.std3').std3_test()     # ... but reachable through the `globals` + `getattr`
tkl_import_module(SOURCE_DIR, 'testlib.py', '.')
print(globals().keys())
base_test()testlib_std1.std1_test()testlib_std1.testlib_std2.std2_test()#testlib.std3.std3_test()                                     # does not reachable directly ...globals()['testlib.std3'].std3_test()                         # ... but reachable through the `globals` + `getattr`

testlib.py

# optional for 3.4.x and higher#import os, inspect##SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("1 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1')
# SOURCE_DIR is restored hereprint("2 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py')
print("3 testlib::SOURCE_FILE: ", SOURCE_FILE)
def base_test():print('base_test')

testlib.std1.py

# optional for 3.4.x and higher#import os, inspect##SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2')
def std1_test():print('std1_test')

testlib.std2.py

# optional for 3.4.x and higher#import os, inspect##SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE)
def std2_test():print('std2_test')

testlib.std3.py

# optional for 3.4.x and higher#import os, inspect##SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE)
def std3_test():print('std3_test')

产出3.7.4):

test::SOURCE_FILE:  <root>/test01/test.pyimport : <root>/test01/testlib.py as testlib -> []1 testlib::SOURCE_FILE:  <root>/test01/testlib.pyimport : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py2 testlib::SOURCE_FILE:  <root>/test01/testlib.pyimport : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py3 testlib::SOURCE_FILE:  <root>/test01/testlib.pydict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib'])base_teststd1_teststd2_teststd3_testimport : <root>/test01/testlib.py as . -> []1 testlib::SOURCE_FILE:  <root>/test01/testlib.pyimport : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py2 testlib::SOURCE_FILE:  <root>/test01/testlib.pyimport : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py3 testlib::SOURCE_FILE:  <root>/test01/testlib.pydict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test'])base_teststd1_teststd2_teststd3_test

在Python3.7.43.2.52.7.16中测试

优点

  • 可以将两个模块作为子模块导入,并且可以将模块的内容导入父模块(或者如果没有父模块,则导入全局)。
  • 可以导入文件名中带有句点的模块。
  • 可以从任何扩展模块导入任何扩展模块。
  • 可以为子模块使用独立名称,而不是默认的不带扩展名的文件名(例如,testlib.std.py作为testlibtestlib.blabla.py作为testlib_blabla等)。
  • 不依赖于sys.path或任何搜索路径存储。
  • 不需要在调用tkl_import_module之间保存/恢复SOURCE_FILESOURCE_DIR等全局变量。
  • [对于3.4.x及更高版本]可以在嵌套的tkl_import_module调用中混合模块命名空间(例如:named->local->namedlocal->named->local等)。
  • [对于3.4.x及更高版本]可以自动将全局变量/函数/类从声明的位置导出到通过tkl_import_module(通过tkl_declare_global函数)导入的所有子模块。

缺点

  • 不支持完全导入:
    • 忽略枚举和子类。
    • 忽略内置项,因为每个类型都必须独占复制。
    • 不要忽略简单可复制的类。
    • 避免复制内置模块,包括所有打包的模块。
  • [对于3.3.x及更低版本]要求在所有调用tkl_import_module的模块中声明tkl_import_module(代码复制)

更新1,2(仅适用于3.4.x及更高版本):

在Python 3.4及更高版本中,您可以通过在顶层模块中声明tkl_import_module来绕过在每个模块中声明tkl_import_module的要求,并且该函数将在单个调用中将自身注入到所有子模块中(这是一种自部署导入)。

更新3

添加函数tkl_source_module作为bashsource的模拟,支持导入时执行保护(通过模块合并而不是导入实现)。

更新4

添加了函数tkl_declare_global以自动将模块全局变量导出到所有子模块,其中模块全局变量不可见,因为它不是子模块的一部分。

更新5

所有的函数都已经移入了addlelib库,参见上面的链接。

有一个专门用于这个:

from thesmuggler import smuggle
# À la `import weapons`weapons = smuggle('weapons.py')
# À la `from contraband import drugs, alcohol`drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')
# À la `from contraband import drugs as dope, alcohol as booze`dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')

它已经在Python版本(Jython和PyPy)中进行了测试,但根据项目的大小,它可能会矫枉过正。

如果我们在同一个项目中有脚本,但在不同的目录装置中,我们可以通过以下方法解决这个问题。

在这种情况下utils.pysrc/main/util/

import syssys.path.append('./')
import src.main.util.utils#orfrom src.main.util.utils import json_converter # json_converter is example method

这是我的两个实用函数,它只使用path lib。它从路径推断模块名称。

默认情况下,它会从文件夹中递归加载所有Python文件,并将init.py替换为父文件夹名称。但您也可以提供Path和/或全局来选择某些特定文件。

from pathlib import Pathfrom importlib.util import spec_from_file_location, module_from_specfrom typing import Optional

def get_module_from_path(path: Path, relative_to: Optional[Path] = None):if not relative_to:relative_to = Path.cwd()
abs_path = path.absolute()relative_path = abs_path.relative_to(relative_to.absolute())if relative_path.name == "__init__.py":relative_path = relative_path.parentmodule_name = ".".join(relative_path.with_suffix("").parts)mod = module_from_spec(spec_from_file_location(module_name, path))return mod

def get_modules_from_folder(folder: Optional[Path] = None, glob_str: str = "*/**/*.py"):if not folder:folder = Path(".")
mod_list = []for file_path in sorted(folder.glob(glob_str)):mod_list.append(get_module_from_path(file_path))
return mod_list

这是一种加载文件的方法,类似于C等。

from importlib.machinery import SourceFileLoaderimport os
def LOAD(MODULE_PATH):if (MODULE_PATH[0] == "/"):FULL_PATH = MODULE_PATH;else:DIR_PATH = os.path.dirname (os.path.realpath (__file__))FULL_PATH = os.path.normpath (DIR_PATH + "/" + MODULE_PATH)
return SourceFileLoader (FULL_PATH, FULL_PATH).load_module ()

实施情况:

Y = LOAD("../Z.py")A = LOAD("./A.py")D = LOAD("./C/D.py")A_ = LOAD("/IMPORTS/A.py")
Y.DEF();A.DEF();D.DEF();A_.DEF();

其中每个文件看起来像这样:

def DEF():print("A");

我发现这是一个简单的答案:

module = dict()
code = """import json
def testhi() :return json.dumps({"key" : "value"}, indent = 4 )"""
exec(code, module)x = module['testhi']()print(x)

添加到Sebastian Rittau的答案:至少对于CPython,有pydoc,虽然没有正式声明,但导入文件就是它的作用:

from pydoc import importfilemodule = importfile('/path/to/module.py')

PS。为了完整起见,在撰写本文时引用了当前的实现:pydoc.py,我很高兴地说,在xkcd 1987的脉络中,它既没有使用问题21436中提到的实现——至少,不是逐字的。

特别的是使用Exec()导入一个具有绝对路径的模块:(exec接受代码字符串或代码对象。而ava接受表达式。)

PYMODULE = 'C:\maXbox\mX47464\maxbox4\examples\histogram15.py';Execstring(LoadStringJ(PYMODULE));

然后使用ava()获取值或对象:

println('get module data: '+evalStr('pyplot.hist(x)'));

使用exec加载模块就像使用通配符命名空间导入:

Execstring('sys.path.append(r'+'"'+PYMODULEPATH+'")');Execstring('from histogram import *');

您可以使用pydoc中的导入文件

from pydoc import importfilemodule = importfile('/full/path/to/module/module.py')name = module.myclass() # myclass is a class inside your python file