假设我有以下脚本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
模块,令牌模块,compile
内置,grammar reference中看到所有这些内容,并在其他各个地方撒上.)
实际上,您可以独立于运行生成的代码来编译模块;这就是内置的compileall
方法所做的.
所以这是第一阶段:编译. Python只有一个其他阶段,实际上是运行代码.除了def或lambda中包含的语句之外,模块中的每个语句都按顺序执行.这意味着导入会在运行时发生,无论您将它们放在模块中的哪个位置.这是将它们全部放在首位的良好卫生的部分原因. def和class也是一样的:这些只是创建特定类型对象的语句,它们会在遇到它们时执行,就像其他任何东西一样.
这里唯一棘手的问题是阶段可能不止一次发生 – 例如,导入仅在运行时执行,但如果您以前从未导入过该模块,则必须进行编译,现在您又回来了在编译时.但是“外部”导入它仍然是运行时,这就是为什么你可以捕获导入抛出的SyntaxError的原因.
无论如何,要回答您的具体问题:
>在编译时.当您将其作为脚本运行时,或者将其作为模块导入时,或者使用compileall编译它时,或者让Python对它有任何意义.实际上,这可以随时发生:如果您尝试在函数中导入此模块,则在调用该函数时,您只会获得一个SyntaxError,这可能是您的程序的一半.
>在执行foo期间,因为def和class只是创建一个新对象并将其分配给一个名称.但Python仍然知道如何创建嵌套函数,因为它已经编译了其中的所有代码.
>将foo = lambda:1 2添加到命名空间而不执行它的方式相同.函数只是一个包含“代码”属性的对象 – 实际上只是一个Python字节码块.您可以将代码类型作为数据进行操作,因为它是数据,与执行数据无关.尝试查看函数的.__ code__,阅读the data model的“代码对象”部分,或者甚至使用disassembler.(您甚至可以使用exec直接使用自定义本地和全局变量执行代码对象,或者将代码对象更改为函数使用!)
>是的,因为import是一个像任何其他的一样普通的旧语句,按顺序执行.但是如果在导入之前还有其他代码,那么它将首先运行.如果它在一个函数中,那么在该函数运行之前你不会得到错误.请注意,导入,就像def和class一样,只是一种奇特的赋值形式.
>仅在执行foo()期间. Python无法知道其他代码是否会在该点之前向您的模块添加do_things,甚至无法完全将my_library更改为其他对象.当您提出要求时,属性查找总是及时完成.
标签:python,python-2-7,ipython 来源: https://codeday.me/bug/20190830/1770068.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。