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

Posted

技术标签:

【中文标题】导入 Python 库并在它们不可用时优雅地处理【英文标题】:Importing Python libraries and gracefully handling if they are not availalble 【发布时间】:2013-12-12 03:26:18 【问题描述】:

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

如果我只有 1 个 try catch 块,我会得到 1 个异常(第一个)。是否有一种模式可以遍历所有库并为每个缺少的库提供单独的异常?

#!/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()

【问题讨论】:

如果导入 sys 失败,您的异常处理程序将完全失败。 我会在这里省略标准库。为什么导入这些文件根本会失败? 如果这些导入中的任何一个失败,为什么你的代码应该工作?您的代码是否足够健壮以处理未定义的 spnp 正如 Martijn 正确指出的那样,这有点毫无意义。但是,如果您出于某种原因坚持不要在后续行中使用以前导入的模块(例如 sys),因为它们可能尚未导入。 我不同意这里的评论者 - 有有效的用例。您可能会运行嵌入式 Python(如在应用程序或嵌入式设备中)而运行时受限,我遇到过这样的混蛋,例如在诺基亚 60 系列手机上。安息吧然而,在此处理仅用于找出您的应用程序在嵌入式设备上崩溃的原因,因为通常标准错误处理程序根本不输出任何内容。 【参考方案1】:

您可以使用__import__ 动态导入模块,允许您通过迭代列表及其名称来导入模块。

例如:

libnames = ['numpy', 'scipy', 'operator']
for libname in libnames:
    try:
        lib = __import__(libname)
    except:
        print sys.exc_info()
    else:
        globals()[libname] = lib

您可以扩展它以处理 import ... as ...from ... import ... 表单,或者稍后手动进行分配,即:

np = numpy
sp = scipy
itemgetter = operator.itemgetter

【讨论】:

我更喜欢这个解决方案,因为它使用基本的python,无需导入额外的库。【参考方案2】:

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

  # 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

有关该主题的更多信息可以在这里找到

http://developer.plone.org/reference_manuals/external/plone.api/contribute/conventions.html#about-imports

正如上面的 cmets 所指出的,Python 标准库模块 (stdlib) 始终可用,除非您在嵌入式环境中运行 Python,并且运行时已被剥离。

【讨论】:

链接说第一个版本不好,因为它可能隐藏循环导入错误。 请注意,虽然这里显示的第一个版本很糟糕,因为它可能会掩盖一些意想不到的东西,但提问者使用的原始版本却不是 - 它会打印发生的实际错误。 请注意,在 Python 3 上,重新引发 ImportError 时可能会嵌套错误。这不适用于 Python 2.x。【参考方案3】:

您可以执行以下操作:

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

【讨论】:

以上是关于导入 Python 库并在它们不可用时优雅地处理的主要内容,如果未能解决你的问题,请参考以下文章

导入文件不可用时如何避免崩溃?..IOS 7

当没有可用的 javascript 时,在 drupal 中优雅地降级 jquery。想法?

如何引用具有相同功能的多个库并在Go中内联切换它们

如何优雅地将dat,txt 或者excel 文件导入python

如何优雅地将dat,txt 或者excel 文件导入python

Python优雅地可视化数据