【问题标题】:Python - Best practice for user-friendly way of checking for missing library dependencies?Python - 检查缺失库依赖项的用户友好方式的最佳实践?
【发布时间】:2020-06-02 19:33:19
【问题描述】:

假设我的 Python 3.6 脚本需要库 foo 中的 bar,它以 imports 开头:

from foo import bar

我想做的是让脚本尝试import,如果foo 在他们的系统上不可用并且他们应该安装它,则向下游用户提供反馈。

到目前为止,我已经设法拼凑出这个可能不是很好的解决方案:

try:
    from foo import bar
except:
    print("Need `foo` library installed")
    exit(1)

我使用print() 是因为我希望这可以直接向用户发送消息,但不确定在异常处理的上下文中这是否是个好主意?

另外,这里至少还有两个问题:

  1. except 子句将适用于在import 期间发生的任何 错误,包括错误不是没有foo 的情况。所以这可能不是对异常处理的好用?
  2. 我的脚本imports 多个库,我必须为每个库创建一个类似于上面的块!

我曾短暂考虑过创建一个 for 循环,该循环通过 list 的库依赖项和 import 每个。例如:

list_of_libraries: list = ["foo", "lorem", "ipsum"]
for library in list_of_libraries:
    try:
        import library
    except:
        print("Need " + library + " library installed")
        exit(1)

但是,这对我来说也很糟糕,因为:

  • 每个循环迭代imports 整个库
  • 它会失败,因为我不认为import 需要string
  • 它并不能真正解决上述问题 1。

我在这里愚蠢地错过了什么吗?什么是实现这个的好方法?谢谢。

编辑: 现有答案,例如 this one,其中讨论了如何在 requirements.txt 中列出依赖项并使用 pip 安装它们。但是,我的问题集中在我可以在 Python 脚本中实现的解决方案以捕获丢失的库并提示用户安装它们

【问题讨论】:

  • 这能回答你的问题吗? Simple dependency management for a Python project
  • 最简单的解决方案是什么都不做。如果导入失败,将会有一条消息(异常回溯)告诉用户缺少什么。
  • 感谢@mkrieger1,但这并不是我所追求的。链接的答案是关于处理 pip 和最佳实践,例如使用 requirements.txt,但我说的是我可以在我的 Python 脚本中做的事情。

标签: python python-3.x exception dependency-management


【解决方案1】:

例外条款

您可以捕获 ModuleNotFoundError(自 Python 3.6 起存在)或 ImportError(适用于所有 Python 版本)以将您的 except 子句限制为导入问题的情况。 ModuleNotFoundErrorImportError 的子类,因此捕获 ImportError 将适用于所有版本的 Python。

错误输出

标准 linux 应用程序中的错误将被写入 stderr 而不是 stdout。所以不要使用普通的print,你可以这样做:

import sys

try:
    from foo import bar
except ImportError:
    print("Need `foo` library installed", file=sys.stderr)
    exit(1)

您可以通过将标准输出重定向到/dev/null 来测试它。您仍然会看到错误消息:

$ python foobar.py >> /dev/null
Need `foo` library installed

可以更好地处理吗?

至于比单独编写每个导入或循环访问所需库更好的方法,遗憾的是我不知道。我已经看到从 Python 2 重命名为 Python 3 的模块之间的 try except ImportError 模式是 used for compatibility。所以对于单个库来说这似乎是正常的,但我没有看到任何大规模检查导入。

【讨论】:

  • 谢谢@Aufziehvogel!这已经很有帮助了。至于“更好的处理”,我认为 import 在循环所需库时不能与 list 类型的 string 项目一起使用,有没有办法创建一个循环来以另一种方式做到这一点?
  • 我想你想使用importlib,尤其是import_module。但是随后您将模块分配给了一个变量,并且不能像普通模块一样使用它。人们似乎通过分配给global() 来解决这个问题。它有效,但我不知道是否有负面影响。在我的试验中,这有效:globals()['foo'] = importlib.import_module('foo'),然后你可以调用像foo.my_function() 这样的函数。
猜你喜欢
  • 2011-10-15
  • 2012-10-09
  • 1970-01-01
  • 2019-08-24
  • 2011-08-16
  • 2022-08-09
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
相关资源
最近更新 更多