如果在解释/ JITing之前将Python源代码编译为字节码,为什么在运行时之前未捕获到此错误?

桃子

我写了以下函数:

def f():
    for i in range(100000):
        print(i)
    some_function_that_doesnt_exist()

运行文件时,这将打印出100000范围内的数字,然后引发错误:NameError: name 'some_function_that_doesnt_exist' is not defined

这是一个关于Python的更广泛问题的示例。如果在Python VM解释(或JIT)之前将Python代码编译为字节码,为什么在编译过程中没有看到此错误?为什么在我们最终看到错误之前打印出100000个数字?在像C这样的纯编译语言中,我们会在编译时看到错误,那么为什么不能在这种“部分编译”语言中看到它呢?

迪纳里

您可以使用以下命令查看python VM运行的内容dis

import dis

def f():
    for i in range(100000):
        print(i)
    some_function_that_doesnt_exist()


dis.dis(f)

将输出:

  4           0 SETUP_LOOP              24 (to 26)
              2 LOAD_GLOBAL              0 (range)
              4 LOAD_CONST               1 (100000)
              6 CALL_FUNCTION            1
              8 GET_ITER
        >>   10 FOR_ITER                12 (to 24)
             12 STORE_FAST               0 (i)

  5          14 LOAD_GLOBAL              1 (print)
             16 LOAD_FAST                0 (i)
             18 CALL_FUNCTION            1
             20 POP_TOP
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK

  6     >>   26 LOAD_GLOBAL              2 (some_function_that_doesnt_exist)
             28 CALL_FUNCTION            0
             30 POP_TOP
             32 LOAD_CONST               0 (None)
             34 RETURN_VALUE

这就是python VM实际运行的方式。从第10到24行可以看到,它实际上是处理打印的。
仅当到达第26行时,python VM才会尝试加载该函数,这将导致名称错误。



稍有不同,当编译语言将代码编译为字节码(例如,从C到汇编)时,函数调用需要确切知道函数在内存中的位置。因此,当您尝试编译不存在的函数时,它将无法将其转换为字节码,因为它将无法查找函数位置。
Python VM可以访问可以实时修改的全局数组,并且在该数组中的查找也是实时的。
正在做:

dis.dis("def some_function_that_doesnt_exist(): 1")

将导致:

  1           0 LOAD_CONST               0 (<code object some_function_that_doesnt_exist at 0x7f38dc90ed20, file "<dis>", line 1>)
              2 LOAD_CONST               1 ('some_function_that_doesnt_exist')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (some_function_that_doesnt_exist)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

第2行从const表中加载函数名称,然后在第4行创建函数后,根据名称在第6行存储它。因此,当下次查找该函数时,python VM将能够找到它。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章