导入Python库并在它们不可用时优雅地处理它们

导入Python库并在它们不可用时优雅地处理它们,python,exception-handling,setup.py,egg,Python,Exception Handling,Setup.py,Egg,我想导入一堆库并捕获异常 如果我只有一个try-catch块,我会得到一个异常(第一个)。是否有一种模式可以迭代所有lib,并为每个缺失的lib单独设置一个异常 #!/usr/bin/env python try: import sys except: print sys.exc_info() try: import numpy as np except: print sys.exc_info() try: import scipy as sp except: print sys.exc_in

我想导入一堆库并捕获异常

如果我只有一个try-catch块,我会得到一个异常(第一个)。是否有一种模式可以迭代所有lib,并为每个缺失的lib单独设置一个异常

#!/usr/bin/env python

try: import sys
except: print sys.exc_info()
try: import numpy as np
except: print sys.exc_info()
try: import scipy as sp
except: print sys.exc_info()
try: import os as os
except: print sys.exc_info()
try: from operator import itemgetter
except: print sys.exc_info()
try: import socket
except: print sys.exc_info()
try: import logging
except: print sys.exc_info()
try: from time import gmtime, strftime
except: print sys.exc_info()

虽然常见,但不鼓励使用以下简单的设计模式及其变体:

  # BAD, hides circular import etc. nested errors 
  try:
       import moolib
  except ImportError:
       raise ImportError("You must install moolib from http://moo.example.com in order to run this app")
而是使用Python包管理器检查库是否可用:

# GOOD
import pkg_resources

try:
    pkg_resources.get_distribution('plone.dexterity')
except pkg_resources.DistributionNotFound:
    HAS_DEXTERITY = False
else:
    HAS_DEXTERITY = True
更多关于这个主题的信息可以在这里找到

正如上面的评论所指出的,Python标准库模块(stdlib)总是可用的,除非您在运行时精简的嵌入式环境中运行Python。

您可以使用动态导入模块,允许您通过迭代带有模块名称的列表来导入模块

例如:

libnames = ['numpy', 'scipy', 'operator']
for libname in libnames:
    try:
        lib = __import__(libname)
    except:
        print sys.exc_info()
    else:
        globals()[libname] = lib
您可以扩展它来处理
导入。。。作为…
和来自。。。导入…表单或稍后手动完成分配,即:

np = numpy
sp = scipy
itemgetter = operator.itemgetter

您可以执行以下操作:

try:
    import sys 
    import os.path
    from logging import handlers
except ImportError as L_err:
    print("ImportError: {0}".format(L_err))
    raise L_err

如果导入
sys
失败,您的异常处理程序将完全失败。我将在这里省略标准库。为什么这些导入会失败?如果这些导入失败了,为什么您的代码会工作?您的代码是否足够健壮,可以处理未定义的
sp
np
?正如Martijn正确指出的那样,这一切都有点毫无意义。但是,如果您出于任何原因坚持不在后续行(例如,
sys
)中使用以前导入的模块,因为它们可能尚未导入。我不同意这里的评论-存在有效的用例。你可能会在运行时出错的情况下运行嵌入式Python(比如在应用程序或嵌入式设备中),我在诺基亚60系列手机上遇到过这样的混蛋。R.I.P.然而,在这种情况下,处理仅用于找出应用程序在嵌入式设备上崩溃的原因,通常,标准错误处理程序不会输出任何内容。该链接指出,第一个版本是错误的,因为它可能隐藏循环导入错误。请注意,虽然此处显示的第一个版本是错误的,因为它可能会掩盖一些非预期的内容,asker使用的原始版本不是-它打印发生的实际错误。请注意,在Python3上,在重新调用ImportError时可以嵌套错误。但这不适用于Python2.x,我更喜欢这个解决方案,因为它使用基本的Python而不需要导入额外的库。