我该如何动态地按其名称字符串导入模块?

23 浏览
0 Comments

我该如何动态地按其名称字符串导入模块?

我正在编写一款 Python 应用程序,它接受一个命令作为参数,例如:

$ python myapp.py command1

我希望该应用程序可扩展,即可以添加实现新命令的新模块,而无需改变主应用程序源代码。树的结构大致如下:

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

因此,我希望应用程序在运行时找到可用的命令模块并执行相应的模块。

Python 定义了一个 __import__() 函数,它接受一个模块名称的字符串:

__import__(name, globals=None, locals=None, fromlist=(), level=0)

该函数导入模块 name,可能使用给定的 globalslocals 来确定如何在软件包上下文中解释名称。 fromlist 给出从给定的 name 模块中导入的对象或子模块的名称。

来源: https://docs.python.org/3/library/functions.html#__import_

因此,我目前的代码如下:

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message
command_module.run()

这个很好用,我只是想知道是否有可能用更典型的方法来实现我们的代码所做的事情。

请注意,我特别不想使用蛋或扩展点。这不是一个开源项目,我也不期望有“插件”。这个点是简化主应用程序代码,消除每次添加新命令模块时修改代码的需要。


另请参阅:如何给定完整路径导入模块?

admin 更改状态以发布 2023年5月21日
0
0 Comments

Python 2.7 和 3.1 及其更高版本的推荐方式是使用 importlib 模块:

importlib.import_module(name, package=None)

导入一个模块。name 参数指定要导入的模块,可以在绝对或相对 terms 中指定 (例如 pkg.mod 或 ..mod)。如果 name 是相对的,则 package 参数必须设置为要充当解析包名称锚点的包的名称 (例如 import_module('..mod', 'pkg.subpkg') 将导入 pkg.mod)。

例如:

my_module = importlib.import_module('os.path')

0
0 Comments

在Python 2.7/3.1之前的版本中,这基本上就是你所需要做的。

对于新版本,请参见Python 2和Python 3的importlib.import_module

或者使用__import__,可以通过以下方式导入一系列的模块:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

Dive Into Python中直接提取。

0