gpt4 book ai didi

python - Python 可执行文件如何解析和执行脚本?

转载 作者:太空宇宙 更新时间:2023-11-03 14:23:22 24 4
gpt4 key购买 nike

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

7年前关闭。




Improve this question




假设我有以下脚本,test.py :

import my_library

bar = 12

def foo():
nested_bar = 21

my_library.do_things()

def nested_foo():
nested_bar += 11
not_a_variable += 1
{$ invalid_syntax

bar = 13
foo()
bar = 14

我很好奇当我运行 python test.py 时到底发生了什么.显然 Python 不只是逐行读取程序 - 否则它不会在实际执行程序之前捕获语法错误。但这使得解释器的工作方式显得有些模糊。我想知道是否有人会帮助我解决问题。特别是,我想知道:
  • Python 在什么时候意识到第 13 行有语法错误?
  • Python 在什么时候读取嵌套函数并将它们添加到 foo 的范围内?
  • 同理,Python如何添加函数foo当它遇到它时到它的命名空间,而不执行它?
  • 假设 my_library是无效的导入。 Python 是否一定会引发 ImportError在执行任何其他命令之前?
  • 假设 my_library是一个有效的模块,但它没有功能do_things .在执行 foo() 期间,Python 会在什么时候意识到这一点?还是以前?

  • 如果有人可以向我指出有关 Python 如何解析和执行脚本的文档,将不胜感激。

    最佳答案

    modules 的教程部分中有一些信息。 ,但我不认为文档对此有完整的引用。所以,这就是发生的事情。

    当您第一次运行脚本或导入模块时,Python 会将语法解析为 AST,然后将其编译为字节码。它还没有执行任何操作;它只是将您的代码编译为基于堆栈的小型机器的指令。这是捕获语法错误的地方。 (您可以在 ast 模块、token 模块、 compile 内置模块、grammar reference 中看到所有这些内容,并散布在其他各个地方。)

    您实际上可以独立于运行生成的代码来编译模块;这就是内置的 compileall 方法可以。

    这就是第一阶段:编译。 Python 只有另一个阶段,即实际运行代码。模块中的每个语句,def 中包含的语句除外或 lambda , 按顺序执行。这意味着 import s 发生在运行时,无论你碰巧把它们放在你的模块中。这是将它们全部放在顶部的良好卫生习惯的部分原因。 def 相同和 class :这些只是创建特定类型对象的语句,它们会在遇到时执行,就像其他任何事情一样。

    这里唯一棘手的一点是这些阶段可以发生不止一次——例如,import仅在运行时执行,但如果您以前从未导入过该模块,则必须对其进行编译,现在您又回到了编译时。但是“在”导入之外它仍然是运行时,这就是为什么你可以捕捉到 SyntaxErrorimport 抛出.

    无论如何,要回答您的具体问题:

  • 在编译时。当你作为脚本运行它,或者当你把它作为一个模块导入,或者当你用 compileall 编译它时,或者以其他方式要求 Python 理解它。实际上,这可能随时发生:如果您尝试在函数中导入此模块,您只会得到 SyntaxError调用该函数时,这可能是您程序的一半。
  • foo 执行期间, 因为 defclass只需创建一个新对象并将其分配给一个名称。但是 Python 仍然知道如何创建嵌套函数,因为它已经编译了其中的所有代码。
  • 以同样的方式添加 foo = lambda: 1 + 2到一个命名空间而不执行它。函数只是一个包含“代码”属性的对象——实际上只是一个 Python 字节码 block 。您可以操纵 code类型为数据,因为它是数据,独立于执行它。尝试查看函数的 .__code__ ,阅读 the data model 的“代码对象”部分, 甚至玩弄 disassembler . (您甚至可以使用 exec 直接使用自定义局部变量和全局变量执行代码对象,或者更改函数使用的代码对象!)
  • 是的,因为 import是一个普通的旧语句,与其他语句一样,按顺序执行。但是如果 import 之前还有其他代码,那将首先运行。如果它在一个函数中,那么在该函数运行之前你不会得到错误。请注意 import , 就像 defclass , 只是一种奇特的赋值形式。
  • 仅在 foo() 执行期间. Python 无法知道其他代码是否会添加 do_things在此之前添加到您的模块,甚至更改 my_library完全指向其他对象。属性查找总是及时完成,当你要求它们时,永远不会提前。
  • 关于python - Python 可执行文件如何解析和执行脚本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24356801/

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