V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
OneAPM
V2EX  ›  Python

从底层理解 Python 的执行[译]

  •  6
     
  •   OneAPM ·
    oneapm · 2015-06-01 14:52:00 +08:00 · 3006 次点击
    这是一个创建于 3490 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Alt text
    OneAPM工程师,常年使用 Python/Perl 脚本,从事 DevOP、测试开发相关的开发工作。业余热爱看书,喜欢 MOOC。

    以下为译文

    最近我在学习 Python 的运行模型。我对 Python 的一些内部机制很是好奇,比如 Python 是怎么实现类似 YIELDVALUEYIELDFROM 这样的操作码的;对于 递推式构造列表(List Comprehensions)、生成器表达式(generator expressions)以及其他一些有趣的 Python 特性是怎么编译的;从字节码的层面来看,当异常抛出的时候都发生了什么事情。翻阅 CPython 的代码对于解答这些问题当然是很有帮助的,但我仍然觉得以这样的方式来做的话对于理解字节码的执行和堆栈的变化还是缺少点什么。GDB 是个好选择,但是我懒,而且只想使用一些比较高阶的接口写点 Python 代码来完成这件事。

    所以呢,我的目标就是创建一个字节码级别的追踪 API,类似 sys.setrace 所提供的那样,但相对而言会有更好的粒度。这充分锻炼了我编写 Python 实现的 C 代码的编码能力。我们所需要的有如下几项,在这篇文章中所用的 Python 版本为 3.5。

    • 一个新的 Cpython 解释器操作码
    • 一种将操作码注入到 Python 字节码的方法
    • 一些用于处理操作码的 Python 代码

    ** 一个新的 Cpython 操作码**

    新操作码:DEBUG_OP

    这个新的操作码 DEBUG_OP 是我第一次尝试写 CPython 实现的 C 代码,我将尽可能的让它保持简单。 我们想要达成的目的是,当我们的操作码被执行的时候我能有一种方式来调用一些 Python 代码。同时,我们也想能够追踪一些与执行上下文有关的数据。我们的操作码会把这些信息当作参数传递给我们的回调函数。通过操作码能辨识出的有用信息如下:

    • 堆栈的内容
    • 执行 DEBUG_OP 的帧对象信息

    所以呢,我们的操作码需要做的事情是:

    • 找到回调函数
    • 创建一个包含堆栈内容的列表
    • 调用回调函数,并将包含堆栈内容的列表和当前帧作为参数传递给它

    听起来挺简单的,现在开始动手吧!声明:下面所有的解释说明和代码是经过了大量段错误调试之后总结得到的结论。首先要做的是给操作码定义一个名字和相应的值,因此我们需要在 Include/opcode.h中添加代码。

    /** My own comments begin by '**' **/  
        /** From: Includes/opcode.h **/  
    
        /* Instruction opcodes for compiled code */  
    
        /** We just have to define our opcode with a free value  
            0 was the first one I found **/  
        #define DEBUG_OP                0  
    
        #define POP_TOP                 1  
        #define ROT_TWO                 2  
        #define ROT_THREE               3
    

    这部分工作就完成了,现在我们去编写操作码真正干活的代码。

    ...................

    查看文章详情

    ...................

    总结

    这个小项目是一个了解 Python 底层的良好途径,包括解释器的 main loop,Python 实现的 C 代码编程、Python 字节码。通过这个小工具我们可以看到 Python 一些有趣构造函数的字节码行为,例如生成器、上下文管理和递推式构造列表。

    这里是这个小项目的完整代码。更进一步的,我们还可以做的是修改我们所追踪的函数的堆栈。我虽然不确定这个是否有用,但是可以肯定是这一过程是相当有趣的。

    原文链接 Understanding Python execution from inside: A Python assembly tracer


    本文作者系OneAPM工程师编译整理。OneAPM是中国基础软件领域的新兴领军企业。专注于提供下一代应用性能管理软件和服务,帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客
    oneapm.com

    4 条回复    2015-06-01 16:16:46 +08:00
    Septembers
        1
    Septembers  
       2015-06-01 15:31:56 +08:00
    我个人不建议将"总结"放上来,这相当于你看完介绍下面放着带剧透属性的点评
    dikcen
        2
    dikcen  
       2015-06-01 15:51:31 +08:00
    回头看下,3.5版没发布啊,最新也就是3.5.0b1。再看原文,应该是5月7号之前版本。版本号能这么简化么?
    OneAPM
        3
    OneAPM  
    OP
       2015-06-01 16:12:04 +08:00
    @Septembers 哈哈,好的。下次我不剧透了,抱歉~
    OneAPM
        4
    OneAPM  
    OP
       2015-06-01 16:16:46 +08:00
    @dikcen 感谢阅读 ,欢迎提出改进建议。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2638 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:31 · PVG 13:31 · LAX 21:31 · JFK 00:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.