首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

第6.3节 Python动态执行之动态编译的compile函数

  • 23-09-22 19:01
  • 3759
  • 13463
blog.csdn.net

Python支持动态代码主要三个函数,分别是compile、eval和exec。本节介绍compile函数的语法和相关使用。compile函数用来编译一段字符串的源码,将其编译为字节码或者AST(抽像语法树)。

一、    语法
compile个内置函数,语法如下:
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
二、    参数解释:
1、    source:是一串字符串的源码,或者是AST(抽像语法树)对象数组,就是需要执行的代码对象。
2、    filename:参数filename用于在执行代码报错的运行时错误消息中显示该参数对应的信息,当source是执行代码从文件中读取的代码字符串时,则可以存放文件名,如果不是从文件里读取源码来编译,那么这里可以放一些用来标识这些代码的字符串,其值理论上是任何字符串,没有特殊要求,一般都放‘’,用于表示前面的source是个字符串,如果source放AST,则可以标识为‘’;
3、    mode:三个取值,分别是'exec'、'single' 、'eval',如果是‘exec’表示编译的是一段代码或模块, 'single'表示编译的是一个单独的语句, 'eval'表示编译的是一个表达式而不是一个语句。
这三种模式中,老猿初步验证凡是'single'模式能编译的就能‘exec’模式编译,‘eval’和二者不能互换。
4、    flags和dont_inherit
这两个参数是组合使用,可选参数 flags 和 dont_inherit 控制在编译 source 时要用到哪个 future 语句。
 如果两者都未提供(或都为零)则会使用调用 compile() 的代码中有效的 future 语句来编译代码。 如果给出了 flags 参数但没有 dont_inherit (或是为零) 则 flags 参数所指定的 以及那些无论如何都有效的 future 语句会被使用。 如果 dont_inherit 为一个非零整数,则只使用 flags 参数 -- 在调用外围有效的 future 语句将被忽略。
future 语句使用比特位来指定,多个语句可以通过按位或来指定。具体特性的比特位可以通过 __future__ 模块中的 _Feature 类的实例的 compiler_flag 属性来获得。
不知道各位有明白的没有,以上这段解释直接来自于Python 标准库,老猿只是照抄,没有看懂,估计涉及Python的高级特性future,以后再研究吧,我们暂时都用缺省值。
5、    optimize:optimize到Python的代码优化机制。
Python为了适应不同的执行要求定义了几种代码优化的策略:
1)    缺省值是-1,表示使用命令行参数-O中获取的优化等级为准;
2)    如果设置值为0,是没有优化,__debug__为true支持debug信息(if __debug__语句下的语句,就是开发者根据需要加入的调试信息)在运行中展示;
3)    如果设置值为1,assert语句被删除,__debug__设置为false确保调试语句不执行;
4)    如果设置值为2,除了设置值为1的功能之外,还会把代码里文档字符串也删除掉,达到最佳优化结果。

三、    compile函数返回结果
1、    如果编译通过,结果可以生成字节码(类型code)或者AST(抽像语法树),字节码可以使用函数exec()或eval来执行,而AST可以使用eval()来继续编译(关于AST的内容本节都不介绍,ATS 对象:Abstract Syntax Tree,抽象语法树,是源代码语法结构的一种抽象表示。关于抽象语法树大家可以参考:https://zhuanlan.zhihu.com/p/26988179;
2、    exec 语句:exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码。需要说明的是在 Python2 中exec不是函数,而是一个内置语句;
3、    如果编译的源码不合法,此函数会触发 SyntaxError 异常;如果源码包含 空字节(空字符串),则3.5版本以前会触发 ValueError 异常,3.5版本后则不会触发可以编译通过并执行。注意:
1)    在 'single' 或 'eval' 模式编译多行代码字符串(这些串必须是一个完整语句或表达式而不是多个语句或表达式)时,输入必须以至少一个换行符结尾;
2)    如果编译足够大或者足够复杂的字符串成 AST 对象时,Python 解释器会因为 Python AST 编译器的栈深度限制而崩溃
四、    例子:
1、    从字符串编译

  1. s=""" 
  2. person=['张三','李四']
  3. for p in person:  print('name=',p)
  4. while(True):
  5.     s=input("I will exit,are you ready(y/n)?")
  6.     if s=='Y': break;
  7.     if s=='y': break;
  8. """
  9. c=compile(s,'','exec')


上述代码包含两个语句,一个s赋值为一段代码的语句(注意这里用的多行字符串是用三个双引号标记的,这与前面讲字符串的内容不同,应该说前面介绍时的三引号是三个单引号,实际上三个双引号也可以,误导了大家非常抱歉),一个编译语句,这里编译用了三个参数,第一个是代码字符串,第二个是代码字符串的来源说明信息,你可以改成任何需要的内容,第三个是编译模式,用的是’exec’,也只能用‘exec’。编译完了就可以执行,等下再讲。
2、    从文件compiler.py读取内容编译

  1. # compiler.py
  2. with open('source.py') as f:
  3.     source = f.read()
  4.     executable = compile(source, 'source.py', 'exec')


涉及文件操作在后面再介绍,这里说明一下,source字符串变量的值是从文件compiler.py中读取的,编译实际上是编译的读取内容,而第二个参数文件名只是说明这些代码串是来源于 source.py,仅在代码有错时报告错误信息中展示文件名,你完全可以改成不相关的内容。    

本节老猿详细介绍了动态执行的代码编译函数compile,其实在进行动态执行时,相关的语句可以经过调用compile函数编译,也可以不调用compile编译。其区别就是编译后对于重复执行的代码会提高效率。
老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
欢迎大家批评指正,谢谢大家关注!

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树首页概览333596 人正在系统学习中
老猿Python
微信公众号
专注Python相关语言、图像音视频处理、AI
注:本文转载自blog.csdn.net的LaoYuanPython的文章"https://blog.csdn.net/LaoYuanPython/article/details/90757058"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top