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

8

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

我觉得 Python 字节码指令 POP_JUMP_IF_FALSE 需要一个 1 字节的操作数,用于告诉它跳转到的指令索引。

以下是相关 CPython 代码摘自ceval.c(注释由我添加):

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内部情况,也许这就像x86中的短跳一样简单。 - qwr
1
字节码操作数由两个字节组成,而不是一个字节。如果需要,还有一个扩展操作码可以提供额外的两个字节,尽管我不确定是否适用于每个指令。无论如何,限制将在单个函数的大小上,而不是整个模块上。 - jasonharper
回答标题中的问题:是的,如果您没有足够的内存。我曾经尝试运行一个自动生成的脚本(它是一些JS(我的意思是...大量的JS)转换为Python),但我无法运行,因为解释器一直崩溃。 - ForceBru
1
@jasonharper:自从3.6版本的字节码更改以来,它们已经成为了一个字节,但文档还没有跟上。不过,使用EXTENDED_ARG操作码时仍然可以达到四个字节。 - user2357112
1个回答

3
注意:我不是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指令,允许使用更大的操作数。

2
我一直在思考为什么我的 dis 输出和你的不一样。直到 Python 3.5,opcode 的 arg 大小为两个字节。Python 3.6 引入了一个优化,使默认大小为1个字节,并引入了一种增加 arg 大小的方法(EXTENDED_ARG opcode)。这是引入更改的问题 https://bugs.python.org/issue27097 和提交 https://github.com/python/cpython/commit/f60bf5f7d6166735e51c30137ea19d289d393ecb。 - Dunes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接