如何正确处理python中的可选功能

杰里米

我正在研究实现科学模型的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 ...语句
  • 将功能取决于特定模块放在单独的文件中

这些选项应该可以使用,但是它们似乎都非常笨拙且难以维护。如果我们想完全删除依赖项怎么办?还是强制性的?

me

当然,最简单的解决方案是将可选依赖项简单地导入需要它们的函数主体中。但是永远正确的PEP 8说:

导入总是放在文件的顶部,紧随任何模块注释和文档字符串之后,以及模块全局变量和常量之前。

我不想违背python大师的最好祝愿,我采取以下方法,它有很多好处...

首先,使用try-except导入

说我的功能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在安装时绝对需要,但是模块的附加功能需要numpysklearn,它们是可选的。


使用此方法,以下是您的特定问题的答案:

  • 如果我们想强制依赖项怎么办?

我们可以简单地将可选依赖项添加到设置工具的必需依赖项列表中。在上面的例子中,我们移动numpyinstall_requiresnumpy然后可以删除所有检查是否存在的代码,但是将其保留不会导致程序中断。

  • 如果我们想完全删除依赖项怎么办?

只需删除以前需要它的任何函数中的依赖项检查即可。如果使用装饰器实现了依赖项检查,则可以对其进行更改,以使其简单地将原始函数传递给原先的函数。

这种方法的好处是将所有导入都放在模块的顶部,这样我就可以一眼看出什么是必需的,什么是可选的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Python:如何正确处理熊猫DataFrame中的NaN,以在Scikit-learn中进行功能选择

来自分类Dev

如何正确处理Python中的浮点运算?

来自分类Dev

如何正确处理Python时钟中的累加器?

来自分类Dev

如何正确处理ReadP上的可选空格?

来自分类Dev

如何正确处理python错误

来自分类Dev

如何正确处理python继承

来自分类Dev

如何正确处理httpClient?

来自分类Dev

如何正确处理scanf()

来自分类Dev

如何正确处理并发?

来自分类Dev

如何正确处理导航

来自分类Dev

如何正确处理Python的`asyncio.gather`中已取消的任务

来自分类Dev

如何使Python 3正确处理MongoDB中的unicode字符串?

来自分类Dev

如何在Python中正确处理Logger文件大小?

来自分类Dev

如何在Python中正确处理Logger文件大小?

来自分类Dev

如何正确处理Hystrix后备广告中的预期错误?

来自分类Dev

如何正确处理打字稿中的promisifyAll?

来自分类Dev

如何正确处理RDBMS中的更新/删除操作?

来自分类Dev

如何正确处理卵石中的APP_MSG_BUSY?

来自分类Dev

如何正确处理嵌套片段中的MaskedWallet响应

来自分类Dev

如何正确处理NSTextField中的<Return> +修饰键?

来自分类Dev

您如何正确处理数组中的哈希?

来自分类Dev

如何正确处理过程宏中的跨度?

来自分类Dev

如何正确处理打字稿中的范围

来自分类Dev

如何正确处理ZeroMQ.js中的连接超时?

来自分类Dev

如何正确处理PL SQL中的触发器?

来自分类Dev

如何确定Outlook中的ContactItem是否显示(正确处理)

来自分类Dev

如何正确处理我的servlet中的异常

来自分类Dev

如何正确处理卵石中的APP_MSG_BUSY?

来自分类Dev

如何正确处理过程宏中的跨度?

Related 相关文章

热门标签

归档