我正在研究实现科学模型的python软件包,我想知道什么是处理可选功能的最佳方法。这是我想要的行为:如果无法导入一些可选的依赖项(例如,在无头计算机上绘制模块),我想在我的类中禁用使用这些模块的功能,并警告用户如果他尝试使用它们以及所有这些而不会破坏执行力。因此以下脚本在任何情况下均适用:
mymodel.dostuff()
mymodel.plot() <= only plots if possible, else display log an error
mymodel.domorestuff() <= get executed regardless of the result of the previous statement
到目前为止,我看到的选项如下:
__init __.py
可用模块并保留它们的列表(但是如何在包装的其余部分中正确使用它?)try import ... except ...
语句这些选项应该可以使用,但是它们似乎都非常笨拙且难以维护。如果我们想完全删除依赖项怎么办?还是强制性的?
当然,最简单的解决方案是将可选依赖项简单地导入需要它们的函数主体中。但是永远正确的PEP 8
说:
导入总是放在文件的顶部,紧随任何模块注释和文档字符串之后,以及模块全局变量和常量之前。
我不想违背python大师的最好祝愿,我采取以下方法,它有很多好处...
说我的功能foo
需求之一numpy
,而我想使其成为可选的依赖项。在模块的顶部,我输入:
try:
import numpy as _numpy
except ImportError:
_has_numpy = False
else:
_has_numpy = True
这里(在except块中)将是打印警告的位置,最好使用warnings
模块。
如果用户致电foo
并且没有numpy怎么办?我在那里扔了例外,并记录了这种行为。
def foo(x):
"""Requires numpy."""
if not _has_numpy:
raise ImportError("numpy is required to do this.")
...
另外,您可以使用装饰器并将其应用于需要该依赖项的任何函数:
@requires_numpy
def foo(x):
...
这样做的好处是可以防止代码重复。
如果您要分发代码,请查找如何向安装配置添加额外的依赖关系。例如,使用setuptools
,我可以编写:
install_requires = ["networkx"],
extras_require = {
"numpy": ["numpy"],
"sklearn": ["scikit-learn"]}
这指定networkx
在安装时绝对需要,但是模块的附加功能需要numpy
和sklearn
,它们是可选的。
使用此方法,以下是您的特定问题的答案:
我们可以简单地将可选依赖项添加到设置工具的必需依赖项列表中。在上面的例子中,我们移动numpy
到install_requires
。numpy
然后可以删除所有检查是否存在的代码,但是将其保留不会导致程序中断。
只需删除以前需要它的任何函数中的依赖项检查即可。如果使用装饰器实现了依赖项检查,则可以对其进行更改,以使其简单地将原始函数传递给原先的函数。
这种方法的好处是将所有导入都放在模块的顶部,这样我就可以一眼看出什么是必需的,什么是可选的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句