如果用户试图运行试图导入尚未安装的模块的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
表现得像我想要的那样?
有没有人知道这个问题的任何现有解决方案?
答案 0 :(得分:6)
您可以将某个地方始终执行(例如在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__
文档here。
答案 1 :(得分:3)
您不必为每次导入捕获ImportError。您可以在脚本的入口点使用全局try..except
块。
您可以使用message属性从ImportError实例获取缺少模块的名称。
例如,如果脚本的入口点是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')
在我看来,第一种策略更好。第二个会使您的代码难以阅读。并将改变语言的重要部分。
答案 2 :(得分:2)
我会在软件包中添加其他模块,导入时打印出更有用的消息,然后引发常规的ImportError。安装true模块后,您的模块将被遮蔽(确保在sys.path的 end 处添加它们所在的目录)。
答案 3 :(得分:1)
替换sys.excepthook
:
orig_excepthook = sys.excepthook
def my_excepthook(type, value, tb):
orig_excepthook(type, value, tb)
if issubclass(type, ImportError):
# print some friendly message
sys.excepthook = my_excepthook