导入时丢失模块的友情错误消息

时间:2009-10-24 18:57:28

标签: python exception-handling

如果用户试图运行试图导入尚未安装的模块的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 个答案:

答案 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