无法使用__import__()动态导入Python模块 - 我知道这是因为它没有出现在sys.modules中

2 投票
1 回答
1388 浏览
提问于 2025-04-15 17:25

我写了一个小脚本。这个脚本的目的是在Python的目录中搜索所有可用的模块(无论它们是否已经安装),然后检查当前加载了哪些模块,接着提供一个选项,让你可以动态加载你选择的模块。这个动态加载是通过使用 __import__() 来实现的,因为我传递给它的是一个字符串——(这就是我遇到问题的地方,稍后我会再说)……然后它还提供了一个“浏览”模块的选项,可以查看这个模块的所有类、函数等等(使用 dir([模块名]))。

问题:

当模块被动态加载时,它是嵌入在一个 try/except 语句中的——如果加载成功,它会报告“模块已加载”,如果失败,它会报告……嗯……“加载失败……”。

比如你输入一个模块的名字,比如叫“uu”的模块,它会显示“已加载”。所以我知道它确实在加载——然而,当我回去调用一个检查所有已加载模块的函数时,结果是空的(使用 sys.modules)。

我在想,Python可能是把这个模块加载到一个临时的地方,而不是 sys.modules,因为当我退出脚本后再检查 sys.modules 时,它并不在里面。

1 个回答

1

Nascent_Notes,脚本写得不错!我试着加载了 uu(命令3),然后打印加载的模块列表(命令2),这两个都运行得很好。

不过,当我尝试“浏览模块”(命令4)时,出现了以下错误:

HlpWiz>>> 4
What module do you want to look more into?:  uu

*An error occurred - probably because the module isn't loaded or is misspelled*

试着运行

#!/usr/bin/env python
import sys
__import__('uu')
print(sys.modules['uu'])
print(dir(uu))

你应该会看到 NameError: name 'uu' is not defined

所以看起来虽然 __import__ 成功加载了 uu 模块,但它并没有把 uu 加入到全局命名空间里——也就是说,变量名 uu 无法直接访问这个模块。不过,你可以通过 sys.modules 来访问它:

因此,把

    var_mod = input("What module do you want to look more into?:  ")
    print "\n attempting to browse... please wait!"
    time.sleep(2)
    browse_mod(zlib = var_mod)

改成

    var_mod = raw_input("What module do you want to look more into?:  ")
    print "\n attempting to browse... please wait!"
    time.sleep(2)
    browse_mod(zlib = sys.modules[var_mod])

使用 raw_inputinput 安全得多(用户无法执行意外或恶意的命令),而且 raw_input 也能满足你的需求。

另外,你还可以把

i = 1
for line in sample:
    print i, line
    i = i + 1

改成更符合 Python 风格的

for i,line in enumerate(sample):
    print i+1, line

补充:

sys.modules 是一个字典(dict 的缩写)。字典就像电话簿——你给它一个名字(通常叫做“键”),它就会返回一个电话号码(或者更一般的“值”)。

在 sys.modules 的情况下,键是模块名(字符串)。值则是模块对象本身。

你可以用方括号的方式来访问字典里的值。所以 uu 只是一个字符串,而 sys.modules['uu'] 就是模块 uu

你可以在这里阅读关于字典的完整介绍:http://docs.python.org/tutorial/datastructures.html#dictionaries

撰写回答