Python 模块的大小是否有限制?
Is there a limit to the size of a Python module?
Python 模块的大小是否有限制?
在我看来 Python 字节码指令 POP_JUMP_IF_FALSE
需要一个 1 字节的操作数,告诉它要跳转到的指令索引。
引用 ceval.c
中的一些相关 CPython 代码(评论我的):
case TARGET(POP_JUMP_IF_FALSE): {
PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = POP();
int err;
if (cond == Py_True) {
Py_DECREF(cond);
FAST_DISPATCH();
}
if (cond == Py_False) {
Py_DECREF(cond);
JUMPTO(oparg); # <--- this
FAST_DISPATCH();
}
这是否意味着 Python 模块不能包含超过 255 个字节码指令?我在这里错过了什么?
注意:我不是Python方面的专家,也绝对不是解释字节码的专家,这是我经过一段时间的实验后发现的。
注意:我使用的是 Python 3.7.3,如果您使用不同的版本,您可能会得到不同的反汇编输出(感谢 @dunes 指出了这一点)。
# module.py
x = 0
while True:
if x == 0:
continue
将产生以下指令:(通过python3 -m dis module.py
)
1 0 LOAD_CONST 0 (0)
2 STORE_NAME 0 (x)
2 4 SETUP_LOOP 14 (to 20)
3 >> 6 LOAD_NAME 0 (x)
8 LOAD_CONST 0 (0)
10 COMPARE_OP 2 (==)
12 POP_JUMP_IF_FALSE 6
4 14 JUMP_ABSOLUTE 6
16 JUMP_ABSOLUTE 6
18 POP_BLOCK
>> 20 LOAD_CONST 1 (None)
22 RETURN_VALUE
偏移量 12 是 POP_JUMP_IF_FALSE
指令。在文件顶部添加一大堆代码后(我只是重复 x = 0
多次):
271 1080 SETUP_LOOP 20 (to 1102)
272 >> 1082 LOAD_NAME 0 (x)
1084 LOAD_CONST 0 (0)
1086 COMPARE_OP 2 (==)
1088 EXTENDED_ARG 4
1090 POP_JUMP_IF_FALSE 1082
273 1092 EXTENDED_ARG 4
1094 JUMP_ABSOLUTE 1082
1096 EXTENDED_ARG 4
1098 JUMP_ABSOLUTE 1082
1100 POP_BLOCK
>> 1102 LOAD_CONST 1 (None)
1104 RETURN_VALUE
编译器在偏移量 1088 处添加了一条 EXTENDED_ARG
指令,允许更大的操作数。
Python 模块的大小是否有限制?
在我看来 Python 字节码指令 POP_JUMP_IF_FALSE
需要一个 1 字节的操作数,告诉它要跳转到的指令索引。
引用 ceval.c
中的一些相关 CPython 代码(评论我的):
case TARGET(POP_JUMP_IF_FALSE): {
PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = POP();
int err;
if (cond == Py_True) {
Py_DECREF(cond);
FAST_DISPATCH();
}
if (cond == Py_False) {
Py_DECREF(cond);
JUMPTO(oparg); # <--- this
FAST_DISPATCH();
}
这是否意味着 Python 模块不能包含超过 255 个字节码指令?我在这里错过了什么?
注意:我不是Python方面的专家,也绝对不是解释字节码的专家,这是我经过一段时间的实验后发现的。
注意:我使用的是 Python 3.7.3,如果您使用不同的版本,您可能会得到不同的反汇编输出(感谢 @dunes 指出了这一点)。
# module.py
x = 0
while True:
if x == 0:
continue
将产生以下指令:(通过python3 -m dis module.py
)
1 0 LOAD_CONST 0 (0)
2 STORE_NAME 0 (x)
2 4 SETUP_LOOP 14 (to 20)
3 >> 6 LOAD_NAME 0 (x)
8 LOAD_CONST 0 (0)
10 COMPARE_OP 2 (==)
12 POP_JUMP_IF_FALSE 6
4 14 JUMP_ABSOLUTE 6
16 JUMP_ABSOLUTE 6
18 POP_BLOCK
>> 20 LOAD_CONST 1 (None)
22 RETURN_VALUE
偏移量 12 是 POP_JUMP_IF_FALSE
指令。在文件顶部添加一大堆代码后(我只是重复 x = 0
多次):
271 1080 SETUP_LOOP 20 (to 1102)
272 >> 1082 LOAD_NAME 0 (x)
1084 LOAD_CONST 0 (0)
1086 COMPARE_OP 2 (==)
1088 EXTENDED_ARG 4
1090 POP_JUMP_IF_FALSE 1082
273 1092 EXTENDED_ARG 4
1094 JUMP_ABSOLUTE 1082
1096 EXTENDED_ARG 4
1098 JUMP_ABSOLUTE 1082
1100 POP_BLOCK
>> 1102 LOAD_CONST 1 (None)
1104 RETURN_VALUE
编译器在偏移量 1088 处添加了一条 EXTENDED_ARG
指令,允许更大的操作数。