2009-10-24 47 views
4

如果用户尝试运行尝试导入尚未安装的模块的python脚本,我想实现一些友好的错误消息。这包括打印如何安装缺少的模块的说明。这样做将是把进口围绕try..catch块关于为缺少的模块导入的Friendlier错误消息

的一种方式,但是这是一个有点难看,因为它会变成一些简单的像

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 

会表现得像我想要的吗?

有没有人知道这个问题的任何现有解决方案?

回答

2

我会将其他模块放入包中,导入时会打印出更有用的消息,然后引发常规ImportError。当安装真正的模块时,你的模块会被遮蔽(确保你在sys.path的处添加他们所在的目录)。

+0

我想,这可能是最好的建议的解决方案。它不依赖任何特殊的“技巧”,因为它应该非常强大。同时,它不需要对源代码进行任何更改(除了可以添加正确的路径到sys.path,这可以轻松处理)。 – pafcu 2009-10-25 14:06:49

5

你可以说,地方,它都会被执行(例如,在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

+0

我想这个问题的一个问题是,如果有其他人提出了相同的想法,它不会很好地发挥。如果其他软件包使用相同的技巧,那么你运气不好(因为如果__import__它会安装另一个版本)。 – pafcu 2009-10-25 14:03:37

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块的外部输入任何东西。这将覆盖模块1和模块2及其导入的所有模块等。

正如你所说,你可以定义自己的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') 

在我看来,拳头策略较好。第二个会让你的代码难以阅读。并将改变语言的重要部分。

+0

第一种方法的问题是它试图解析错误消息(甚至没有,它只是假定模块名称在特定位置)。这只是不能假设:错误消息可能是本地化的或在Python版本 – pafcu 2009-10-24 20:02:59

+0

而不是'print“之间进行更改您没有安装模块{0}”.format(error.message [16:]) '只是**'打印(错误)'**对于2.7.10和3.5.0都适用 – CrandellWS 2015-10-15 01:40:49

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