【发布时间】:2014-07-05 20:50:56
【问题描述】:
我正在从另一个软件内部运行一个 python 脚本(它提供了一个 python 接口来操作它的数据结构)。
我正在优化我的代码以提高速度,并想看看我的断言对性能有什么影响。
我无法使用python -O。我还有哪些其他选项可以以编程方式禁用 python 代码中的所有断言?变量__debug__(由-O 标志清除)不能分配给:(
【问题讨论】:
我正在从另一个软件内部运行一个 python 脚本(它提供了一个 python 接口来操作它的数据结构)。
我正在优化我的代码以提高速度,并想看看我的断言对性能有什么影响。
我无法使用python -O。我还有哪些其他选项可以以编程方式禁用 python 代码中的所有断言?变量__debug__(由-O 标志清除)不能分配给:(
【问题讨论】:
内置变量 [
__debug__] 的值是在 解释器启动。
因此,如果您无法控制 python 解释器的启动方式,那么您似乎无法禁用断言。
这里有一些其他选项:
如果您的所有断言语句都单独出现在行上,那么 也许你可以删除它们
sed -i 's/assert /pass #assert /g' script.py
请注意,如果断言之后有其他代码,这将破坏您的代码。例如,上面的 sed 命令会在如下一行中注释掉 return:
assert x; return True
这会改变你程序的逻辑。
如果您有这样的代码,最好手动删除断言。
可能有一种方法可以通过解析您的
带有tokenize 模块的脚本,但编写这样的程序
删除断言可能需要比手动操作更多的时间
删除断言,特别是如果这是一次性工作。
如果其他软件接受 .pyc 文件,则有一个
尽管注意a Python
core developer warns against this(参见 Éric Araujo 于 2011-09-17 的评论),但似乎在我的机器上工作的肮脏技巧。假设您的脚本名为script.py。
制作一个名为 temp.py 的临时脚本:
import script
python -O temp.py。这将创建 script.pyo。script.py 和script.pyc(如果存在)移出PYTHONPATH
或其他软件正在读取的任何目录以找到您的
脚本。script.pyo --> script.pyc。现在,当其他软件尝试导入您的脚本时,它会
只找到 pyc 文件,该文件已删除断言。
例如,如果script.py 看起来像这样:
assert False
print('Got here')
然后运行 python temp.py 现在将打印 Got here 而不是引发 AssertionError。
【讨论】:
assert 语句的if 分支将无法编译:)
正如@unutbu 所描述的,没有官方的方法可以做到这一点。然而,一个简单的策略是在某处定义一个类似 _test 的标志(例如,作为函数的关键字参数,或作为模块中的全局变量),然后将其包含在您的断言语句中,如下所示:
def f(x, _test=True):
assert not _test or x > 0
...
然后,如果需要,您可以在该函数中禁用断言。
f(x, _test=False)
【讨论】:
您可以使用环境变量来执行此操作,如this other answer 中所述。设置PYTHONOPTIMIZE=1 相当于使用-O 选项启动Python。例如,这适用于嵌入 Python 3.5 的 Blender 2.78:
blender --python-expr 'assert False; print("foo")'
PYTHONOPTIMIZE=1 blender --python-expr 'assert False; print("foo")'
第一个命令打印回溯,而第二个命令只打印“foo”。
【讨论】: