我正在为嵌套的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对上述列表进行的3种方式比较:
我不明白在y对象中加载了什么-它是基本matplotlib加上其他东西,但它缺乏我想要的信息,这是来自matplotlib的主要类。文本包。屏幕截图(x列表)中最上面的蓝色部分
请不要把狮身人面像作为不同的方法。
模块从列表中自动安装和导入
下面的脚本可以很好地使用子模块和伪子模块。
# 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)
我开发了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()
这里唯一的特殊性是自定义实例的params列表(param1, param2, param3)。
花了一些时间试图从一个列表中导入模块,这是让我大部分的方法的线程-但我没有掌握___import____ -的用法
这里是如何从字符串中导入模块,并获得与导入相同的行为。并尝试/除了错误情况。:)
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 + "\n")
sys.exit(1)
是的,对于python 2.7>,您有其他选项-但对于2.6<,这是可行的。
除了使用importlib,还可以使用exec方法从字符串变量中导入模块。
这里我展示了一个使用exec方法从itertools包中导入组合方法的例子:
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)
__import__函数可能有点难以理解。
如果你改变
i = __import__('matplotlib.text')
to
i = __import__('matplotlib.text', fromlist=[''])
然后我将参考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)之前,请参阅注意事项)。