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是执行代码从文件中读取的代码字符串时,则可以存放文件名,如果不是从文件里读取源码来编译,那么这里可以放一些用来标识这些代码的字符串,其值理论上是任何字符串,没有特殊要求,一般都放‘<string>’,用于表示前面的source是个字符串,如果source放AST,则可以标识为‘<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、    从字符串编译

s=""" 
person=['张三','李四']
for p in person:  print('name=',p)
while(True):
    s=input("I will exit,are you ready(y/n)?")
    if s=='Y': break;
    if s=='y': break;
"""
c=compile(s,'<string>','exec')

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

2、    从文件compiler.py读取内容编译

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

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

本节老猿详细介绍了动态执行的代码编译函数compile,其实在进行动态执行时,相关的语句可以经过调用compile函数编译,也可以不调用compile编译。其区别就是编译后对于重复执行的代码会提高效率。

老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。

欢迎大家批评指正,谢谢大家关注!

第6.3节 Python动态执行之动态编译的compile函数的更多相关文章

  1. python能够执行,但编译第三包遇到 python.h no such file or directory

    python能够执行,但编译第三包遇到 python.h no such file or directory 这个问题是由于没有安装python-devel, 安装此包就能够解决次问题,在Linux下 ...

  2. C#动态执行字符串(动态创建代码)

    在编写C#程序的时候,有时我们需要动态生成一些代码并执行.然而C#不像JavaScript有一个Eval函数,可以动态的执行代码.所有这些功能都要我们自己去完成.如下是实例. 动态创建代码: usin ...

  3. angularjs 动态加载指令------编译服务$compile

    场景: 我们写了一个自定义的指令,这条指令需要一些数据,而这些数据需要在某些操作之后才能就绪,这时候,我们就需要在数据就绪之后,动态加载指令. 示例: js: $scope.$watch('repor ...

  4. 第6.6节 Python动态执行小结

    一.    Python动态执行支持通过输入数据流或文件传入Python源代码串,进行编译后执行,可以通过这种方式扩展Python程序的功能: 二.    动态执行方法可能导致恶意攻击,因此使用时需要 ...

  5. 第6.2节 Python特色的动态可执行方法简介

    一.    基本概念 动态可执行,是指在代码中通过外部输入或代码嵌入的常量字符串包含代码的方式提供Python代码,要求Python执行这些代码.这样就可以达到开放式运行的效果,提高程序的能力和灵活性 ...

  6. 第6章 Python中的动态可执行方法 第6.1节 Python代码编译

    在介绍动态可执行方法前,本节先介绍一下Python代码编译有关的知识,因为部分内容和动态执行有些关联. 一.    Python解释器的功能 Python虽然是解释型语言,但Python代码也是可编译 ...

  7. 第6.4节 Python动态表达式计算:eval函数详述

    在Python动态执行的函数中,eval是用于执行表达式计算的函数,这个函数用于执行字符串中包含的一个表达式或其编译后对应的代码,不能适用于执行Python语句和完整的代码. 一.    语法 1.  ...

  8. 第8.20节 Python中限制动态定义实例属性的白名单:__slots__

    一. 引言 按照<第7.10节 Python类中的实例变量定义与使用>.<第7.14节Python类中的实例方法解析>中的介绍,当定义了一个类,并且创建了该类的实例后,可以给该 ...

  9. Python之PyFrameObject动态执行环境

    Python虚拟机中的执行环境 Python的虚拟机实际上是在模拟操作系统运行可执行文件的过程,首先,我们先来讲一下普通的x86的机器上,可执行文件是以一种什么方式运行的. 图1-1 图1-1所展示的 ...

随机推荐

  1. 1到n整数中1出现的次数

    1到n整数中1出现的次数 题目描述 输入一个整数n, 求1~n这n个整数的十进制表示中1出现的次数. 例如, 输入12, 1~12这些整数中包含1的数字有1, 10, 11和12, 1一共出现了4次 ...

  2. sdasd

    create PROCEDURE v4(in c_year int) BEGIN declare num int(10) default 0; declare num1 int(10); select ...

  3. Python基本数据类型与数据结构(数据挖掘学习)

    前言 最近工作和研究涉及到数据挖掘和机器学习,出于归纳和总结知识的目的写下这一系列的文章,这一系列文章将会包括Python的基本数据类型和数据结构,函数和面向对象相关的知识,然后会介绍数据挖掘和机器学 ...

  4. delphi 设置默认控件得到焦点

    如果同一窗体有多个按钮的话,追踪源码发现最后是taborder来的 如: 在空白窗体上拖入两个button (btn1,btn2) 如果在btn2设置default = True 运行后,默认焦点还是 ...

  5. 准备数据集用于flink学习

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. prometheus监控golang服务实践

    一.prometheus基本原理介绍 prometheus是基于metric采样的监控,可以自定义监控指标,如:服务每秒请求数.请求失败数.请求执行时间等,每经过一个时间间隔,数据都会从运行的服务中流 ...

  7. Linux程序开发中如何判断目录是否为根目录?

    问题引入 判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢? 思路分析 熟悉Lin ...

  8. Maven项目关系

    Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),其中最重要的就是POM文件,可以指定项目类型,项目关系等信息,maven项目之间有三种关系. 依赖 ...

  9. ctfshow之Web入门刷题记(从89开始,持续更新)

    0x01Web89-99PHP特性payload Web89 include("flag.php"); highlight_file(__FILE__); if(isset($_G ...

  10. [python应用]python简单图片抓取

    前言 emmmm python简单图片抓取 1 import requests 2 import threading 3 import queue 4 from subprocess import P ...