给定完整路径如何导入模块?

时间:2008-09-15 22:30:55

标签: python configuration python-import python-module

如何在完整路径下加载Python模块?请注意,该文件可以位于文件系统中的任何位置,因为它是一个配置选项。

33 个答案:

答案 0 :(得分:1065)

对于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

答案 1 :(得分:360)

向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

答案 2 :(得分:19)

听起来你不想专门导入配置文件(它有很多副作用和涉及的额外复杂性),你只想运行它,并能够访问生成的命名空间。标准库以runpy.run_path

的形式专门为其提供API
from runpy import run_path
settings = run_path("/path/to/file.py")

该接口在Python 2.7和Python 3.2 +

中可用

答案 3 :(得分:19)

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

凌乱,但它确实有效。

configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

答案 4 :(得分:16)

您可以使用

load_source(module_name, path_to_file) 
来自imp module

方法。

答案 5 :(得分:14)

如果您的顶级模块不是文件但是打包为__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'](正如你在上面的导入之后那样) ),后者必须作为前“as discussed here

的foo属性出现

答案 6 :(得分:13)

我想出了一个稍微修改过的@SebastianRittau's wonderful answer版本(对于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中对路径进行编码的优点是machinery不会尝试从扩展中找出文件的类型。这意味着您可以使用此方法加载类似.txt文件的内容,但如果未指定加载器,则无法使用spec_from_file_location加载,因为.txt不在importlib.machinery.SOURCE_SUFFIXES中。

答案 7 :(得分:12)

您的意思是加载还是导入?

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

/foo/bar.py

你可以这样做:

import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar

答案 8 :(得分:11)

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

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

答案 9 :(得分:11)

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

临时

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

永久

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

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

信用/来源:saarrrranother stackexchange question

答案 10 :(得分:10)

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')

答案 11 :(得分:8)

我相信您可以使用imp.find_module()imp.load_module()加载指定的模块。您需要将模块名称从路径中分离出来,即如果您要加载/home/mypath/mymodule.py,则需要执行以下操作:

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

......但是应该完成工作。

答案 12 :(得分:3)

这应该有效

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)

答案 13 :(得分:3)

您可以使用pkgutil模块(特别是walk_packages方法)获取当前目录中的包列表。从那里使用importlib机器来导入你想要的模块是微不足道的:

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!

答案 14 :(得分:3)

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

这似乎使用了Python 3.4中不推荐使用的模块。我不会假装理解为什么,但它似乎在一个程序中起作用。我找到了克里斯'解决方案在命令行上运行,但不在程序内部。

答案 15 :(得分:3)

我并不是说它更好,但为了完整起见,我想建议exec函数,在python 2和3中都可用。 exec允许您在全局作用域或内部作用域中执行任意代码,作为字典提供。

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

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

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

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

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

答案 16 :(得分:3)

要从给定文件名导入模块,您可以临时扩展路径,并在finally块reference:中恢复系统路径

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

答案 17 :(得分:3)

创建python模块test.py

import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3

创建python模块test_check.py

from test import Client1
from test import Client2
from test import test3

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

答案 18 :(得分:2)

在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 *

答案 19 :(得分:2)

我制作了一个使用imp的包。我称之为import_file,这就是它的用法:

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

http://code.google.com/p/import-file/

答案 20 :(得分:2)

在运行时导入包模块(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 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)

答案 21 :(得分:1)

添加到Sebastian Rittau的回答中: 至少对于 CPython 来说,有 pydoc,虽然没有正式声明,但导入文件就是这样做的:

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

PS。为了完整起见,在撰写本文时引用了当前的实现:pydoc.py,我很高兴地说,本着{ {3}} 它不使用 xkcd 1987 中提到的任何实现——至少,不是逐字逐句的。

答案 22 :(得分:1)

使用yes yes代替importlib包的简单解决方案(针对Python 2.7进行测试,尽管它也适用于Python 3):

imp

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

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")

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

答案 23 :(得分:1)

非常简单的方法:假设您想要具有相对路径的导入文件../../ MyLibs / pyfunc.py


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

但是,如果你没有后卫,你终于可以获得一条很长的路径

答案 24 :(得分:0)

此答案是塞巴斯蒂安·里陶(Sebastian Rittau)对评论的回答的补充:“但是,如果您没有模块名称怎么办?”这是一种在给定文件名的情况下获取可能的python模块名称的快速而又肮脏的方法-它只是沿树爬上,直到找到没有__init__.py文件的目录,然后将其转换回文件名。对于Python 3.4+(使用pathlib),这很有意义,因为Py2人可以使用“ imp”或其他方式进行相对导入:

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

当然有改进的可能,可选的__init__.py文件可能需要进行其他更改,但是如果您总体上拥有__init__.py,就可以解决问题。

答案 25 :(得分:0)

将此添加到答案列表中,因为我无法找到有效的内容。这将允许在3.4:

中导入已编译的(pyd)python模块
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()

答案 26 :(得分:0)

我基于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 space
sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory
import tacklelib as tkl

tkl.tkl_init(tkl)

# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.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 here
print("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.py
import : <root>/test01/testlib.py as testlib -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <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.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_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_test
std1_test
std2_test
std3_test
import : <root>/test01/testlib.py as . -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <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.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_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_test
std1_test
std2_test
std3_test

在Python 3.7.43.2.52.7.16中测试过

专家

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

缺点

  • [对于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与bash source类似,在导入时具有执行保护功能(通过模块合并而不是导入来实现)。

更新4

添加了功能tkl_declare_global,可将模块全局变量自动导出到所有子模块,这些模块由于不属于子模块而看不到模块全局变量。

更新5

所有功能都已移入铲斗库,请参见上面的链接。

答案 27 :(得分:0)

有一个package专门用于此目的:

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)上进行了测试,但是根据您的项目大小,它可能会显得过大。

答案 28 :(得分:0)

如果我们在同一项目中有脚本,但是在不同的目录方式下,则可以通过以下方法解决此问题。

在这种情况下,utils.py位于src/main/util/

import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method

答案 29 :(得分:0)

这是我的2个仅使用pathlib的实用程序函数。它从路径推断模块名称 默认情况下,它递归地从文件夹中加载所有python文件,并用父文件夹名称替换 init .py。但是,您也可以指定路径和/或glob来选择一些特定文件。

from pathlib import Path
from importlib.util import spec_from_file_location, module_from_spec
from 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.parent
    module_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

答案 30 :(得分:0)

这是一种加载文件的方法,例如 C 等。

from importlib.machinery import SourceFileLoader
import 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");

答案 31 :(得分:0)

我发现这是一个简单的答案: 模块 = dict()

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

答案 32 :(得分:-1)

我认为最好的方法来自官方文档(29.1. imp — Access the import internals):

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