当前位置:  开发笔记 > 编程语言 > 正文

如何根据名称导入模块?

如何解决《如何根据名称导入模块?》经验,为你挑选了7个好方法。

我正在编写一个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)

该函数导入模块名称,可能使用给定的全局变量和局部变量来确定如何解释包上下文中的名称.fromlist给出了应该从name给出的模块导入的对象或子模块的名称.

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

所以目前我有类似的东西:

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

command_module.run()

这很好用,我只是想知道是否可能有更惯用的方法来完成我们正在使用此代码.

请注意,我特别不想使用鸡蛋或扩展点.这不是一个开源项目,我不希望有"插件".重点是简化主应用程序代码,并在每次添加新命令模块时无需修改它.



1> Harley Holco..:

使用早于2.7/3.1的Python,这就是你如何做到的.

对于较新的版本,看到importlib.import_module了Python的2和和Python 3中.

你也可以使用exec.

或者使用__import__您可以通过执行以下操作导入模块列表:

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

直接从Dive Into Python中扯下来.


正如Denis Malinovsky在下面指出的那样,这个解决方案的另一个问题是python文档本身建议不使用`__import__`.2.7文档:"因为这个函数是供Python解释器使用而不是一般用途所以最好使用importlib.import_module()..."当使用python3时,`imp`模块解决了这个问题,就像monkut提到下面.
exec的差异是什么?
OP的这个解决方案的一个问题是捕获一个或两个不良"命令"模块的异常使得他/她的整个命令应用程序在一个例外上失败.我个人想循环遍历每个__​​import__独立包装在一个try:mods = __ import __()\nexcept ImportError as error:report(error)允许其他命令继续工作而坏的修复.

2> Denis Malino..:

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

importlib.import_module(name,package = None)

导入模块.name参数指定以绝对或相对术语导入的模块(例如pkg.mod或..mod).如果名称是以相对术语指定的,那么package参数必须设置为包的名称,该包用作解析包名的锚(例如import_module('.. mod','pkg.subpkg')将导入pkg.mod).

例如

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


文档使用`__import__`函数建议[反对](https://docs.python.org/2/library/functions.html#__import__),以支持上述模块.
这适用于导入`os.path`; 如何从os.path导入*`?
我在这里得到答案/sf/ask/17360801/即.调用`globals().update(my_module .__ dict)`
由哪个来源或权威机构推荐?
@NamGVU,这是一种危险的方法,因为它会污染你的全局变量并且可以覆盖任何具有相同名称的标识符.您发布的链接具有此代码的更好,改进版本.

3> monkut..:

注意:从Python 3.4开始,不推荐使用imp,而是支持importlib

如上所述,imp模块为您提供加载功能:

imp.load_source(name, path)
imp.load_compiled(name, path)

我之前用过这些来执行类似的操作.

在我的例子中,我使用所需的已定义方法定义了一个特定的类.一旦我加载了模块,我将检查该类是否在模块中,然后创建该类的实例,如下所示:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst


好又简单的解决方案。我写了一个类似的文章:http://stamat.wordpress.com/dynamic-module-import-in-python/但您有一些缺陷:异常情况如何?IOError和ImportError?为什么不先检查编译版本,然后再检查源版本。期望一个类会降低您案例的可重用性。
在目标模块中构造MyClass的行中,您将添加对类名称的冗余引用.它已经存储在`expected_class`中,因此您可以执行`class_inst = getattr(py_mod,expected_name)()`.

4> gimel..:

使用imp模块或更直接的__import__()功能.



5> Jonathan..:

如果你想在当地人:

>>> mod = 'sys'
>>> locals()['my_module'] = __import__(mod)
>>> my_module.version
'2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]'

同样适用 globals()



6> Greg Hewgill..:

你可以使用exec:

exec "import myapp.commands.%s" % command


然后,您可以执行getattr(myapp.commands,command)来访问该模块.

7> Brandt..:

Nowadays you should use importlib.

Import a source file

The docs actually provide a recipe for that, and it goes like:

import sys
import importlib.util

file_path = 'pluginX.py'
module_name = 'pluginX'

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(module)

Import a package

Importing a package (e.g., pluginX/__init__.py) under your current dir is actually straightforward:

import importlib

pkg = importlib.import_module('pluginX')

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(pkg)

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有