动态加载Python模块

63 投票
6 回答
73199 浏览
提问于 2025-04-15 12:02

在Python中,如何在程序运行时动态地向一个包添加模块。

我想从外部进程向包目录中添加模块,并能够在我的程序中使用这些新模块:

import package

def doSomething(name):
    pkg = __import__("package." + name)
    mod = getattr(pkg, name)
    mod.doSomething()

我该怎么做呢?

6 个回答

19

在编程中,有时候我们会遇到一些问题,比如代码运行不正常或者出现错误。这些问题可能是因为我们没有正确理解某些概念,或者在写代码的时候犯了一些小错误。

比如,有些人可能会在使用某个功能的时候,不太清楚这个功能是怎么工作的,或者它需要什么样的输入。这就像你在做一道菜的时候,如果不知道食材的用法,可能就会做出不太好吃的菜。

所以,遇到问题的时候,首先要冷静下来,仔细检查自己的代码,看看是不是哪里写错了,或者有没有遗漏什么重要的步骤。同时,也可以去查找一些相关的资料,看看别人是怎么解决类似的问题的。

记住,编程是一个不断学习和实践的过程,遇到困难是很正常的。只要坚持下去,就一定能找到解决办法。

import importlib

module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()
23

Bastien已经回答了这个问题,不过我想分享一个我用来从子文件夹加载所有模块到字典中的函数,可能对你有帮助:

def loadModules():
    res = {}
    import os
    # check subfolders
    lst = os.listdir("services")
    dir = []
    for d in lst:
        s = os.path.abspath("services") + os.sep + d
        if os.path.isdir(s) and os.path.exists(s + os.sep + "__init__.py"):
            dir.append(d)
    # load the modules
    for d in dir:
        res[d] = __import__("services." + d, fromlist = ["*"])
    return res

这个函数是用来根据第一个函数加载的模块中的类来创建一个对象的:

def getClassByName(module, className):
    if not module:
        if className.startswith("services."):
            className = className.split("services.")[1]
        l = className.split(".")
        m = __services__[l[0]]
        return getClassByName(m, ".".join(l[1:]))
    elif "." in className:
        l = className.split(".")
        m = getattr(module, l[0])
        return getClassByName(m, ".".join(l[1:]))
    else:
        return getattr(module, className)

使用这些函数的一个简单方法是这样的:

mods = loadModules()
cls = getClassByName(mods["MyModule"], "submodule.filepy.Class")
obj = cls()

显然,你可以把所有“services”子文件夹的引用替换成参数。

62

你的代码差不多是对的。

可以看看这个__import__函数。

def doSomething(name):
    name = "package." + name
    mod = __import__(name, fromlist=[''])
    mod.doSomething()

撰写回答