基于已安装的模块编写条件语句的Pythonic方式是什么?

5

作为一个来自C++领域的开发者,我习惯于根据编译时由CMake等工具确定的标志编写条件编译。我想知道最符合Python风格的模仿这种功能的方法。例如,取决于是否找到一个模块,这是我目前设置的:

import imp

try:
    imp.find_module('petsc4py')
    HAVE_PETSC=True
except ImportError:
    HAVE_PETSC=False

那么我可以在 Python 代码的其他部分中使用 HAVE_PETSC。这样做是可行的,但我想知道这是否是在 Python 中正确的做法。


4
为什么要使用 imp 而不是直接 import petsc4py 并在找不到时捕获异常? - khelwood
根据我的经验,“Pythonism”通常更喜欢“宁愿请求宽恕,也不要事先征得许可”,而不是“三思而后行”,所以正如@khelwood所说,你应该使用try-except。虽然如果你实际上不需要使用petsc4py,那么你的代码可能就是符合Python风格的,我不知道。 - wjandrea
可能是 Python 中的条件模块导入 的重复问题。 - Sayse
2个回答

7

可以的,你甚至可以直接发出导入命令,并使用模块名称本身作为标志 - 就像这样:

try:
    import petsc4py
except ImportError
    petsc4py = None

在任何使用之前,请测试 petsc4py 的真实性。

实际上,检查它是否存在,然后尝试导入它,由于两个操作都会触发 ImportError,因此感觉不符合 Python 风格。但是,使用一个 HAVE_PETSC 变量进行检查是可以的 - 它可以在上面的 try/except 之后创建,方法是 HAVE_PETSC = bool(petsc4py)


谢谢你的回答。最后一个问题:我采用了C++的方式来命名这种类型的变量(HAVE_PETSC),但是在Python中可能有不同的约定吗? - aaragon
不,我认为对于那些在执行过程中不应该改变的变量来说,全大写加下划线是可以的。 - jsbueno
实际上,检查它是否存在,然后再尝试导入它,由于冗余感觉不符合Python的风格。那么在使用模块之前检查模块是否存在也是一样的吗?在我看来,根据某些依赖项加载自己的代码会更少冗余,或者更好的方法是失败并显示错误消息“没有安装X模块,使用pip install X==someversionifrequired进行安装”,其中功能将是它自己的模块,当被加载时会抛出这样的异常。 - user11877195
如果没有try/except步骤,你的代码根本无法运行 - 甚至不能打印出某个功能不可用或者打印提示如何安装依赖项。如果是完整的、非可选的依赖项,那么是的,代码应该假定它已经被安装,并且如果没有安装就让错误传播(并让安装程序处理依赖项)。 - jsbueno

0

你现在的做法基本上是可以的。事实上,Python标准库使用了类似的范例:“尝试导入某些东西,如果由于某种原因无效,则以某种方式设置变量” 多个 地方。在程序后面检查布尔值是否设置比每次都进行单独的try/except块要快。

在你的情况下,可能最好的方法就是这样:

try:
    import petsc4py
    HAVE_PETSC = True
except ImportError:
    HAVE_PETSC = False

你的代码在范式层面上是可行的,但在这种情况下没有真正的理由通过importlib进行操作(而且你可能不应该使用imp,因为它在Python的最新版本中已经被弃用了)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接