禁用python的assert()而不使用-0标志

时间:2011-12-28 14:07:19

标签: python debugging assert

我正在从不同的软件中运行python脚本(它提供了一个python接口来操纵其数据结构)。

我正在优化我的代码速度,并希望看到我的断言对性能有什么影响。

我无法使用python -O。我有什么其他选项,以编程方式禁用python代码中的所有断言?变量__debug__(由-O标志清除)无法分配给:(

3 个答案:

答案 0 :(得分:9)

The docs say

  

内置变量[__debug__]的值在确定时确定   翻译开始。

因此,如果您无法控制python解释器的启动方式,那么看起来您无法禁用断言。

接下来是其他一些选择:

  1. 最安全的方法是手动删除所有断言语句。
  2. 如果所有的断言语句都是单独出现在行上,那么 也许你可以用

    删除它们
    sed -i 's/assert /pass #assert /g' script.py
    

    请注意,如果其他代码出现在assert之后,这将破坏您的代码。例如,上面的sed命令会将return注释掉,如下所示:

    assert x; return True
    

    会改变程序的逻辑。

    如果您有这样的代码,最好手动删除断言。

  3. 可能有办法通过解析你的方式以编程方式删除它们 脚本与tokenize模块,但编写这样的程序 删除断言可能比手动操作花费更多时间 删除断言,特别是如果这是一次性工作。

  4. 如果另一个软件接受.pyc文件,则有一个 肮脏的伎俩似乎在我的机器上工作,虽然注意a Python core developer warns against this(参见ÉricAraujo对2011-09-17的评论)。假设您的脚本名为script.py

    • 创建一个名为temp.py的临时脚本:

      import script
      
    • 运行python -O temp.py。这会创建script.pyo
    • 从您的PYTHONPATH中移出script.pyscript.pyc(如果存在) 或其他软件正在阅读的目录以查找您的 脚本。
    • 重命名script.pyo - > script.pyc

    现在,当其他软件尝试导入您的脚本时,它会 只找到已移除断言的pyc文件。

    例如,如果script.py如下所示:

    assert False
    print('Got here')
    

    然后运行python temp.py现在会打印Got here而不是引发AssertionError。

答案 1 :(得分:1)

您可以使用环境变量执行此操作,如this other answer中所述。设置PYTHONOPTIMIZE=1相当于使用-O选项启动Python。例如,这适用于Blender 2.78,它嵌入了Python 3.5:

blender --python-expr 'assert False; print("foo")'

PYTHONOPTIMIZE=1 blender --python-expr 'assert False; print("foo")'

第一个命令打印回溯,而第二个命令打印“foo”。

答案 2 :(得分:0)

正如@unutbu所描述的那样,没有正式的方法可以做到这一点。但是,一个简单的策略是在某处定义类似_test的标志(例如,作为函数的关键字参数,或作为模块中的全局变量),然后在断言语句中包含它,如下所示:

def f(x, _test=True):
    assert not _test or x > 0
    ...

然后,如果需要,您可以在该功能中禁用断言。

f(x, _test=False)