使用“__import__”从字符串变量导入模块与普通导入语句产生不同的结果

2024-12-13 08:37:00
admin
原创
157
摘要:问题描述:我正在编写嵌套 matplotlib (MPL) 库的文档(个人),该库与 MPL 自己提供的库不同,由感兴趣的子模块包提供。我正在编写 Python 脚本,希望它能够自动生成未来 MPL 版本的文档。我选择了感兴趣的子模块/包,并想要列出它们的主要类,从中我将生成列表并用它进行处理pydoc。问题...

问题描述:

我正在编写嵌套 matplotlib (MPL) 库的文档(个人),该库与 MPL 自己提供的库不同,由感兴趣的子模块包提供。我正在编写 Python 脚本,希望它能够自动生成未来 MPL 版本的文档。

我选择了感兴趣的子模块/包,并想要列出它们的主要类,从中我将生成列表并用它进行处理pydoc

问题是我找不到一种方法来指示 Python 从字符串加载子模块。以下是我尝试的示例:

import matplotlib.text as text
x = dir(text)
i = __import__('matplotlib.text')
y = dir(i)
j = __import__('matplotlib')
z = dir(j)

以下是通过 pprint 对上述列表进行的三向比较:

在此处输入图片描述

我不明白y对象中加载了什么 - 它是基础matplotlib加上其他东西,但它缺少我想要的信息,即来自包的主要类。它是屏幕截图(列表)matplotlib.text顶部的蓝色部分。x


解决方案 1:

__import__功能可能有点难以理解。

如果你改变

i = __import__('matplotlib.text')

i = __import__('matplotlib.text', fromlist=[''])

然后i将参考matplotlib.text

在 Python 3.1 或更高版本中,您可以使用importlib

import importlib

i = importlib.import_module("matplotlib.text")

一些注释

  • 如果你尝试从子文件夹导入某些内容./feature/email.py,则代码将如下所示importlib.import_module("feature.email")

  • 在 Python 3.3 之前,如果文件夹中没有__init__.py您要导入的文件,则您将无法导入任何内容(在决定是否要保留该文件以实现向后兼容之前,请参阅注意事项,pytest例如)。

解决方案 2:

importlib.import_module就是你要找的。它返回导入的模块。

import importlib

# equiv. of your `import matplotlib.text as text`
text = importlib.import_module('matplotlib.text')

此后您可以访问模块中的任何内容text.myclass,如text.myfunction、等。

解决方案 3:

花了一些时间尝试从列表中导入模块,这是帮助我完成大部分工作的线程 - 但我不明白 import_ 的用法 -

因此,以下是如何从字符串导入模块,并获得与导入相同的行为。还有 try/except 错误情况。:)

  pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
  for module in pipmodules:
      try:
          # because we want to import using a variable, do it this way
          module_obj = __import__(module)
          # create a global object containging our module
          globals()[module] = module_obj
      except ImportError:
          sys.stderr.write("ERROR: missing python module: " + module + "
")
          sys.exit(1)

是的,对于 python 2.7> 您还有其他选择 - 但对于 2.6<,这是有效的。

解决方案 4:

除了使用之外,importlib还可以使用exec方法从字符串变量导入模块。

这里我展示了使用该方法combinationsitertools包中导入方法的一个例子exec

MODULES = [
    ['itertools','combinations'],
]

for ITEM in MODULES:
    import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
    exec(import_str)

ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
    print(elements)

输出:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)

解决方案 5:

您还可以使用exec内置函数将任何字符串作为 Python 代码执行。

In [1]: module = 'pandas'
   ...: function = 'DataFrame'
   ...: alias = 'DF'

In [2]: exec(f"from {module} import {function} as {alias}")

In [3]: DF
Out[3]: pandas.core.frame.DataFrame

对我来说,这是解决我的问题最易读的方法。

解决方案 6:

模块自动安装并从列表导入

下面的脚本可以很好地与子模块和伪子模块配合使用。

# PyPI imports
import pkg_resources, subprocess, sys

modules   = {'lxml.etree', 'pandas', 'screeninfo'}
required  = {m.split('.')[0] for m in modules}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing   = required - installed

if missing:
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
    subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])

for module in set.union(required, modules):
    globals()[module] = __import__(module)

测试:

print(pandas.__version__)
print(lxml.etree.LXML_VERSION)

解决方案 7:

我开发了以下 3 个有用的功能:

def loadModule(moduleName):
    module = None
    try:
        import sys
        del sys.modules[moduleName]
    except BaseException as err:
        pass
    try:
        import importlib
        module = importlib.import_module(moduleName)
    except BaseException as err:
        serr = str(err)
        print("Error to load the module '" + moduleName + "': " + serr)
    return module

def reloadModule(moduleName):
    module = loadModule(moduleName)
    moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
    if (modulePath.endswith(".pyc")):
        import os
        os.remove(modulePath)
        module = loadModule(moduleName)
    return module

def getInstance(moduleName, param1, param2, param3):
    module = reloadModule(moduleName)
    instance = eval("module." + moduleName + "(param1, param2, param3)")
    return instance

每次我想要重新加载一个新实例时,我只需要像这样调用 getInstance():

myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)

最后我可以调用新实例中的所有函数:

myInstance.aFunction()

这里唯一的特殊性是自定义实例的参数列表(param1、param2、param3)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用