Python模块的大小是否有限制?

Avi*_*ohn 7 python interpreter bytecode

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();
    }
Run Code Online (Sandbox Code Playgroud)

这是否意味着Python模块不能包含超过255个字节码指令?我在这里想念什么?

asy*_*nts 3

注意:我不是 Python 专家,也不是解释字节码的专家,这只是我经过一段时间的实验后发现的。

注意:我使用的是 Python 3.7.3,如果您使用不同的版本,您可能会得到不同的反汇编输出(感谢@dunes 指出了这一点)。

# module.py
x = 0
while True:
  if x == 0:
    continue
Run Code Online (Sandbox Code Playgroud)

将产生以下指令:(通过python3 -m dis module.py

# module.py
x = 0
while True:
  if x == 0:
    continue
Run Code Online (Sandbox Code Playgroud)

偏移量 12 处是POP_JUMP_IF_FALSE指令。在文件顶部添加一大堆代码后(我只是重复了x = 0很多次):

  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
Run Code Online (Sandbox Code Playgroud)

编译器EXTENDED_ARG在偏移量 1088 处添加了一条指令,允许使用更大的操作数。

  • 我想知道为什么我没有得到与你相同的 dis 输出。在 3.5 之前,操作码的 arg 大小为两个字节。3.6 引入了一项优化,使默认大小为 1 字节,并在需要时增加 arg 大小的方法(EXTENDED_ARG 操作码)。这是引入更改 https://bugs.python.org/issue27097 并提交 https://github.com/python/cpython/commit/f60bf5f7d6166735e51c30137ea19d289d393ecb 的问题 (2认同)