缺失模块的导入时更友好的错误信息
我想在用户尝试运行一个Python脚本时,如果这个脚本要导入的模块没有安装,就给出一些更友好的错误提示。这包括打印出如何安装缺失模块的说明。
一种方法是把导入模块的代码放在一个try..catch块里,但这样看起来有点麻烦,因为这会把简单的代码变成
import some_module
变成这样
try:
import some_module
except ImportError, e:
handle_error(e)
而且每个文件都需要加上这个代码。此外,ImportError似乎没有地方存储缺失模块的名字(除了错误信息本身),所以如果你需要知道缺失的模块名(就像我需要的那样),你就得在每个导入语句周围都加一个单独的try..catch。解析模块名也不是个好办法,因为ImportError的错误信息可能会随着Python版本的不同而变化,或者根据用户的语言环境不同而变化。
我想我可以用sys.excepthook来捕获所有异常,并把除了ImportError以外的异常都传递出去。或者说,是否有可能定义一些像这样
safe_import some_module
的东西,让它按照我想要的方式工作呢?
有没有人知道解决这个问题的现成方法?
4 个回答
你不需要为每一个导入都捕获ImportError(导入错误)。你可以在脚本的入口点使用一个全局的try..except
块。
你可以通过ImportError实例的message属性获取缺失模块的名称。
举个例子,如果你的脚本入口文件是main.py:
if __name__ == '__main__':
try:
import module1
import module2
module1.main()
except ImportError as error:
print "You don't have module {0} installed".format(error.message[16:])
不要在try..except
块外导入任何东西。这将涵盖module1、module2以及它们导入的所有模块,依此类推。
正如你所说的,你可以定义自己的import_safe
函数:
def import_safe(module):
try:
return __import__(module)
except ImportError as error:
print "You don't have module {0} installed".format(error.message[16:])
然后你可以使用这个函数:
sys = import_safe('sys')
gtk = import_safe('gkt')
在我看来,第一个策略更好。第二种方法会让你的代码难以阅读,并且会改变语言的一个重要部分。
你可以把这段代码放在一个总是会被执行的地方,比如说在site.py或者sitecustomize.py文件里:
import __builtin__
realimport = __builtin__.__import__
def myimport(modname, *a):
try:
return realimport(modname, *a)
except ImportError, e:
print "Oops, couldn't import %s (%s)" % (modname, e)
print "Here: add nice directions and whatever else"
raise
__builtin__.__import__ = myimport
想了解更多关于__import__
的内容,可以查看它的文档,链接在这里。
我会在这个包里添加一些额外的模块,当你导入它们的时候,它们会先打印出一些更有帮助的信息,然后再抛出一个普通的导入错误(ImportError)。当真正的模块安装好后,你的这些模块就会被隐藏起来(确保你把它们所在的目录放在 sys.path 的最后)。