3

我们的主应用程序有一些额外的功能,用户可以启用。这些功能在他们自己的目录中。这些功能可能需要额外的依赖。我正在考虑将它们放在一个requires.txt文件中。在运行时,我们想让人们知道该功能是否会中断。我目前正在考虑这样的事情:

def checkfeature(feature):
  everything_okay = True
  f = pkg_resources.resource_stream(feature, "requires.txt")
  with f:
    for r in pkg_resources.parse_requirements(f):
      if pkg_resources.working_set.find(r) is None:
        print "%r not found, please install, otherwise this feature does not work" % (r,)
        everything_okay = False
  return everything_okay

这是正确的、蟒蛇式的做事方式吗?这有意义吗?

小更新:为什么如此复杂,而不是try: import ... except ImportError: ...像一个答案中建议的那样:

  1. 我们的插件可能有很多依赖项。创建如下所示的实际代码非常冗长。
  2. 某些插件可能需要特定版本的包。需要包装特定测试或pkg_resources无论如何都要使用的测试。所以这就是我上面的想法使用 pkg_resources 的原因。
  3. 我们想为可以运行的插件运行单元测试。在单元测试中处理 ImportError 并不好。拥有一个can_we_unit_test_this_plugin(plugin)函数会让事情变得更容易。

第二次更新:extra_requireinsetup.py呢?

  1. 人们经常想念安装那些。好吧,不好的借口。
  2. 我的愿景是,从上面提到的各个子目录中为各个功能setup.py加载直接。但这确实是下一步。extra_requirerequires.txt
4

1 回答 1

7

通常,您只需尝试导入依赖项,并ImportError优雅地处理异常:

try:
    import dependency
except ImportError:
    # dependency missing, issue a warning
    import warnings
    warnings.warn('dependency not found, please install to enable xyz feature')

extras_require您可以在基于 setuptools 的setup.py脚本的条目中列出此类依赖项。pipeasy_install并且zc.buildout所有人都可以处理安装此类附加设备。请参阅声明“附加”(具有自己依赖项的可选功能)

如果您有这些,您可以使用该extras_require条目列出最低版本要求。是的,用户可能已经安装了旧版本的依赖项;我只是清楚地记录要求。真的,测试功能,而不是版本。如果您因为添加了某个 API 方法而需要更新版本?测试该方法而不是版本。

但是,听起来好像您可能希望将插件打包为单独的包,然后. extras_require我会使用入口点来注册和枚举此类插件。这样您就不需要测试导入包,您只需枚举已注册的入口点。每个插件都列出了自己的依赖项并拥有自己的单元测试。

于 2013-04-10T14:06:46.040 回答