什么';Python3.5和Python3.6的源代码有什么不同?
当运行我的测试程序时,我得到了一个如上所述的错误。 最后我发现Python3.5和Python3.6的源代码之间几乎没有什么区别。 只有一行: 蟒蛇3.5什么';Python3.5和Python3.6的源代码有什么不同?,python,c,python-3.x,python-internals,Python,C,Python 3.x,Python Internals,当运行我的测试程序时,我得到了一个如上所述的错误。 最后我发现Python3.5和Python3.6的源代码之间几乎没有什么区别。 只有一行: 蟒蛇3.5 testing on ../../test/test_patm.py python: Python/compile.c:4420: int assemble_lnotab(struct assembler *, struct instr *): Assertion `d_lineno >= 0' failed. Aborted P
testing on ../../test/test_patm.py
python: Python/compile.c:4420: int assemble_lnotab(struct assembler *,
struct instr *): Assertion `d_lineno >= 0' failed.
Aborted
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;
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;
...
如果我只是删除了断言(d_lineno>=0)代码>?您使用的是调试版本3.5。在Python 3.5和任何早期版本中,单个字节码块(即模块或函数的字节码)中的行号必须是单调的,即每个操作码必须映射到源代码中的一行,其行号必须大于或等于先前操作码的行号。这是在调试版本中检查过的;在Python的发行版中,assert
不会在中编译,但生成的行号选项卡无论如何都是无效的
这是在上一节中讨论的。行号单调性的要求被认为不利于优化,许多优化会重新组织生成的字节码。因此,在3.6中删除了该检查以及使行号delta成为有符号整数的其他更改
您可以非常安全地注释掉这个断言,因为发布版本无论如何都会消除它,但不要期望调试在生成的代码中正常工作,因为行号选项卡现在无效。
另一种方法是,如果您正在重新组织AST中的行或类似的内容,则可以将所有行号设置为0,而不仅仅是缺少的行号;也可以生成不违反单调性规则的伪行号
生成的AST出现了一个巧合的问题,因为会将0的行号写入任何缺少行号的节点。如果AST的某些部分包含行号,因为它们源自
AST.parse
,那么生成的AST树很可能会打破单调性要求——这同样只会导致Pythons<3.6的非发布版本出现问题
另一个与此bug无关的变化是从字节码到wordcode的变化,这也是在Python3.6中引入的。在这里,每个操作码将是一个16位字,而不是一个可能带有扩展参数的8位字节。这就是偏移量乘以
sizeof(_Py_CODEUNIT)的原因代码>您正在使用3.5的调试版本。在Python 3.5和任何早期版本中,单个字节码块(即模块或函数的字节码)中的行号必须是单调的,即每个操作码必须映射到源代码中的一行,其行号必须大于或等于先前操作码的行号。这是在调试版本中检查过的;在Python的发行版中,assert
不会在中编译,但生成的行号选项卡无论如何都是无效的
这是在上一节中讨论的。行号单调性的要求被认为不利于优化,许多优化会重新组织生成的字节码。因此,在3.6中删除了该检查以及使行号delta成为有符号整数的其他更改
您可以非常安全地注释掉这个断言,因为发布版本无论如何都会消除它,但不要期望调试在生成的代码中正常工作,因为行号选项卡现在无效。
另一种方法是,如果您正在重新组织AST中的行或类似的内容,则可以将所有行号设置为0,而不仅仅是缺少的行号;也可以生成不违反单调性规则的伪行号
生成的AST出现了一个巧合的问题,因为会将0的行号写入任何缺少行号的节点。如果AST的某些部分包含行号,因为它们源自AST.parse
,那么生成的AST树很可能会打破单调性要求——这同样只会导致Pythons<3.6的非发布版本出现问题
另一个与此bug无关的变化是从字节码到wordcode的变化,这也是在Python3.6中引入的。在这里,每个操作码将是一个16位字,而不是一个可能带有扩展参数的8位字节。这就是偏移量乘以sizeof(_Py_CODEUNIT)的原因
我看到另一个区别,d字节码
乘以sizeof(\u Py\u CODEUNIT)
@MartijnPieters这是它的定义<代码>类型定义uint16_t_Py_代码单位那么你的代码是什么,为什么它会触发断言错误?我不会从Python代码中删除断言,不,它表明您在其他地方有bug。您在3.6上测试过您的程序吗?@MartijnPieters为什么我的代码会导致这个问题是因为我没有更改ast的lineno
,它可能看起来不正确,但不会导致Python3.6中的任何错误!我看到另一个区别,d字节码
乘以sizeof(\u Py\u CODEUNIT)
@MartijnPieters这是它的定义<代码>类型定义uint16_t_Py_代码单位那么你的代码是什么,为什么它会触发断言错误?我不会从Python代码中删除断言,不,它表明您在其他地方有bug。您在3.6上测试过您的程序吗?@MartijnPieters为什么我的代码会导致这个问题是因为我没有更改ast的lineno
,它可能看起来不正确,但不会导致Python3.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;