gpt4 book ai didi

python - Python3.5和Python3.6的源码有什么区别?

转载 作者:太空宇宙 更新时间:2023-11-04 00:35:04 24 4
gpt4 key购买 nike

 testing on ../../test/test_patm.py
python: Python/compile.c:4420: int assemble_lnotab(struct assembler *,
struct instr *): Assertion `d_lineno >= 0' failed.
Aborted

当运行我的测试程序时,我得到了上面给出的错误。最后发现Python3.5和Python3.6的源代码差别很小。只有一行:

Python3.5

static int
assemble_lnotab(struct assembler *a, struct instr *i)
{
int d_bytecode, d_lineno;
Py_ssize_t len;
unsigned char *lnotab;

d_bytecode = a->a_offset - a->a_lineno_off;
d_lineno = i->i_lineno - a->a_lineno;

assert(d_bytecode >= 0);
assert(d_lineno >= 0); // the only difference

if(d_bytecode == 0 && d_lineno == 0)
return 1;
...

python 3.6

static int
assemble_lnotab(struct assembler *a, struct instr *i)
{
int d_bytecode, d_lineno;
Py_ssize_t len;
unsigned char *lnotab;

d_bytecode = (a->a_offset - a->a_lineno_off) * sizeof(_Py_CODEUNIT);
d_lineno = i->i_lineno - a->a_lineno;

assert(d_bytecode >= 0);

if(d_bytecode == 0 && d_lineno == 0)
return 1;

如果我刚刚删除 assert(d_lineno >= 0); 会怎样?

最佳答案

您使用的是 3.5 的调试版本。在 Python 3.5 和任何之前的版本中,单个字节码 block (即模块或函数的字节码)中的行编号必须单调,即每个操作码必须映射到源代码中的一行,其行号必须大于或等于上一个操作码的行号。这曾经在调试版本中检查过;在 Python 的发布版本中,assert 不会被编译,但生成的行号选项卡无论如何都是无效的。

这在 Issue 26107 中讨论过在 bugs.python.org .行号的单调性要求被认为不利于优化,其中许多优化会重新组织生成的字节码。因此,在 3.6 中删除了检查以及其他更改,这些更改使行号增量成为有符号整数。

您可以非常安全地注释掉 this 断言,因为无论如何发布版本都会将其删除,但不要期望调试在生成的代码中正常工作,因为行号选项卡是现在无效。

作为替代方案,如果您在 AST 或类似的东西中重新组织行,您可以将所有 行号设置为 0 - 而不仅仅是丢失的行号;或者您可以生成不违反单调性规则的假行号。


生成的 AST 出现巧合问题,如 ast.fix_missing_locations会将 0 的行号写入任何缺少行号的节点。如果 AST 的某些部分包含行号,因为它们源自 ast.parse,则生成的 AST 树很可能会破坏单调性要求 - 这只会再次导致非发布版本出现问题Pythons < 3.6.


另一个与这里的 bug 无关的变化是从字节码到 wordcode 的变化,这也是在 Python 3.6 中引入的。这里每个操作码都是一个 16 位字,而不是一个带有可能扩展参数的 8 位字节。这就是偏移量乘以 sizeof(_Py_CODEUNIT); 的原因。

关于python - Python3.5和Python3.6的源码有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45935451/

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