无法使用__import__()动态导入Python模块 - 我知道这是因为它没有出现在sys.modules中
我写了一个小脚本。这个脚本的目的是在Python的目录中搜索所有可用的模块(无论它们是否已经安装),然后检查当前加载了哪些模块,接着提供一个选项,让你可以动态加载你选择的模块。这个动态加载是通过使用 __import__()
来实现的,因为我传递给它的是一个字符串——(这就是我遇到问题的地方,稍后我会再说)……然后它还提供了一个“浏览”模块的选项,可以查看这个模块的所有类、函数等等(使用 dir([模块名])
)。
问题:
当模块被动态加载时,它是嵌入在一个 try/except
语句中的——如果加载成功,它会报告“模块已加载”,如果失败,它会报告……嗯……“加载失败……”。
比如你输入一个模块的名字,比如叫“uu”的模块,它会显示“已加载”。所以我知道它确实在加载——然而,当我回去调用一个检查所有已加载模块的函数时,结果是空的(使用 sys.modules
)。
我在想,Python可能是把这个模块加载到一个临时的地方,而不是 sys.modules
,因为当我退出脚本后再检查 sys.modules
时,它并不在里面。
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_input
比 input
安全得多(用户无法执行意外或恶意的命令),而且 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