gpt4 book ai didi

python - 当 Python 处于优化模式时,如何对某些行为进行单元测试?

转载 作者:太空宇宙 更新时间:2023-11-04 03:19:08 25 4
gpt4 key购买 nike

Python 允许您通过传递 -O 选项以“优化模式”运行脚本。如果我将此脚本保存为“assert.py”:

assert False
print("Hello")

然后这两个 Python 调用会产生不同的输出(一个打印异常消息和堆栈跟踪,而另一个则打招呼):

python -m assert
python -O -m assert

Python 脚本的作者可以通过检查全局名称__debug__ 的值来确定Python 是否处于优化模式。这允许我们根据是否在优化模式下运行来做不同的事情。

假设如果 Python 处于优化模式,我想做一件事,如果不是,我想做另一件完全不同的事情。这很简单——我们可以使用 if __debug__:。但现在假设我想对每种情况下的行为是否正确进行单元测试。我应该怎么做?

我突然想到我可以设置 __debug__ 的值,但是你不能这样做:

>>> __debug__ = False
File "<stdin>", line 1
SyntaxError: assignment to keyword
>>>

最佳答案

考虑这段代码:

assert 123

if __debug__:
do_something()

优化后的字节码将为空。 assert 和 bare if __debug__ 语句是在字节码编译期间评估的,而不是在运行时。因此,即使您成功更改了 __debug__(例如使用 setattr(builtins, '__debug__', True)),您仍然无法执行该代码。

唯一的方法是运行测试套件两次,第一次不使用 -O,然后使用 -O。显然,您可以将这部分自动化,您不必手动完成。


为了完整性:

$ python3
>>> dis.dis('assert 123')
1 0 LOAD_CONST 0 (123)
3 POP_JUMP_IF_TRUE 12
6 LOAD_GLOBAL 0 (AssertionError)
9 RAISE_VARARGS 1
>> 12 LOAD_CONST 1 (None)
15 RETURN_VALUE
>>> dis.dis('if __debug__: do_something()')
1 0 LOAD_NAME 0 (do_something)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 POP_TOP
7 LOAD_CONST 0 (None)
10 RETURN_VALUE

$ python3 -O
>>> dis.dis('assert 123')
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
>>> dis.dis('if __debug__: do_something()')
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE

请注意,只有裸露的 if __debug__ 语句被优化掉了。如果您使用复杂的条件,它们将出现在字节码中:

$ python3 -O
>>> dis.dis('if __debug__ and something_else: do_something()')
1 0 LOAD_NAME 0 (__debug__)
3 POP_JUMP_IF_FALSE 22
6 LOAD_NAME 1 (something_else)
9 POP_JUMP_IF_FALSE 22
12 LOAD_NAME 2 (do_something)
15 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
18 POP_TOP
19 JUMP_FORWARD 0 (to 22)
>> 22 LOAD_CONST 0 (None)
25 RETURN_VALUE

关于python - 当 Python 处于优化模式时,如何对某些行为进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35245203/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com