1.cpython是码查什么?pypy是什么?python和这两个东西有什么关系
2.教你阅读 Cpython 的源码(一)
3.Python C语言API教程(一、用C写一个Python包)
4.深入理解 Python 虚拟机:列表(list)的码查实现原理及源码剖析
5.python是如何执行的?
6.cpython中的PyObject等对象入门
cpython是什么?pypy是什么?python和这两个东西有什么关系
p >本文旨在介绍Python的主流实现CPython是如何执行源代码的。我们将以当前主分支的码查CPython 3.版本为例,解释从源代码到执行的码查全过程。
p > Python语言内嵌有一个编译器。码查首先,码查自动发卡APP源码需要对源代码进行词法分析,码查将字符串转化为一个个单词,码查以便进一步处理。码查这一过程主要发生在`Parser/tokenizer.c`文件中,码查由手工编写实现。码查
p > 完成词法分析后,码查接下来是码查语法分析阶段。通过这一阶段,码查CPython真正理解了代码的码查结构。自Python 3.版本起,CPython采用了一种新的PEG解析器。
p > PEG,全称Parser Expression Generator,理念是通过描述你设计的语法,生成相应的解析代码。在CPython项目中,`Grammar/python.gram`文件描述了Python语法,通过`Tools/peg_generator/pegen/`生成器转换为解析代码,位于`Parser/parser.c`。我有幸参与过`Grammar/python.gram`的修改,无需修改语法即可保持其稳定。
p > PEG语法广泛应用于多种场景,因为它允许自定义描述语法,同时生成器也可以自定义。在CPython中,`Tools/peg_generator/pegen/metagrammar.gram`描述了元语法,可以用来生成不同语言的解析代码,并在多种语言中实现。
p > 语法分析后,nfafactory 源码解析结果是抽象语法树(AST),声明在`Include/internal/pycore_ast.h`,并由`ast`模块对外提供接口。
p > 有了AST,下一步是将其转换为字节码。CPython的核心是解释执行,执行的内容即为字节码。这些字节码保存在`__pycache__/*.pyc`文件中,每个小版本的字节码都可能发生变化,用户不应假设兼容性。我们可以通过`dis`模块查看编译后的结果。
p > 字节码生成过程涉及符号查找、指令优化等多个步骤,尤其是在Python 3.的性能优化中,有一部分就是在字节码层面进行的改进。这部分主代码位于`Python/compile.c`。
p > 字节码生成的输入是AST,输出为Python字节码。整个转换过程由`_PyParser_ASTFromFile`函数串联起来。
p > 完成字节码生成后,下一步是执行字节码。这通常是一个大的循环过程,主要在`_PyEval_EvalFrameDefault`中实现,包含了大量的`switch case`结构。
p > `Python/generated_cases.c.h`文件包含了几乎所有的字节码实现,并且通过`Python/bytecodes.c`生成。CPython执行的核心通常称为CPython VM(虚拟机)。
p > 在真正执行之前,还需要内置对象的支持。基本的内置对象如`str`、`list`和`dict`在Python中至关重要。这些对象的C实现构成了CPython VM的重要部分,位于`Objects`目录下,并编译在VM程序中。pigeon的源码
p > Python内置了许多基本库,它们的代码通常位于`Lib`目录下。同时,CPython VM提供了丰富的C API,允许用户编写C扩展,并方便地在C扩展和Python VM之间传递对象。
p > 为了提供基本功能,CPython必须使用一些操作系统提供的原生C函数,因此内置了许多C扩展。例如,`os`模块的C实现位于`Modules`目录下,这些模块通过CPython VM动态加载。
p > Python最初的定位是胶水语言,大量C扩展极大地丰富了CPython的生态系统,同时也是其他Python实现如PyPy等的限制。
p > 最后,将所有这些组件组织起来的代码位于`Python/pythonrun.c`中,经过这一系列步骤后,代码终于可以执行了。
教你阅读 Cpython 的源码(一)
目录1. CPython 介绍
在Python使用中,你是否曾好奇字典查找为何比列表遍历快?生成器如何记忆变量状态?Cpython,作为流行版本,其源代码为何选择C和Python编写?Python规范,内存管理,这里一一揭示。 文章将深入探讨Cpython的内部结构,分为五部分:编译过程、解释器进程、编译器和执行循环、对象系统、以及标准库。了解Cpython如何工作,从源代码下载、编译设置,作品源码文件到Python模块和C模块的使用,让你对Python核心概念有更深理解。 2. Python 解释器进程 学习过程包括配置环境、文件读取、词法句法解析,直至抽象语法树。理解这些步骤,有助于你构建和调试Python代码。 3. Cpython 编译与执行 了解编译过程如何将Python代码转换为可执行的中间语言,以及字节码的缓存机制,将帮助你认识Python的编译性质。 4. Cpython 中的对象 从基础类型如布尔和整数,到生成器,深入剖析对象类型及其内存管理,让你掌握Python数据结构的核心。 5. Cpython 标准库 Python模块和C模块的交互,以及如何进行自定义C版本的安装,这些都是Cpython实用性的体现。 6. 源代码深度解析 从源代码的细节中,你会发现编译器的工作原理,以及Python语言规范和tokenizer的重要性,以及内存管理机制,如引用计数和垃圾回收。 通过本文,你将逐步揭开Cpython的神秘面纱,成为Python编程的高手。继续深入学习,提升你的Python技能。 最后:结论 第一部分概述了源代码、编译和Python规范,后续章节将逐步深入,让你在实践中掌握Cpython的核心原理。 更多Python技术,持续关注我们的sockettool源码c公众号:python学习开发。Python C语言API教程(一、用C写一个Python包)
Python的C语言API教程(一:实践入门)
Python的C语言API在提升程序性能和实现跨平台适配方面发挥着关键作用。通过官方API,开发者可以直接操作Python解释器的底层,绕过Python的GIL限制,达到加速效果,如cython和codon等工具相比,C语言API更为直接有效。
Python的C语言API还支持本地化适配,例如PyQT库,它根据操作系统和硬件调整图形界面。在机器学习框架TensorFlow这类需要底层优化和硬件适配的场景中,C语言API更是不可或缺。
理解C语言API有助于深入学习CPython,因为Python的执行实际上就是调用C语言API。Python源码阅读者会发现,熟悉API有助于解析CPython的内部工作原理。
要进行Python的C开发,首先需要配置环境。Windows用户需安装Visual Studio Build Tools,选择Python开发和C++桌面开发工作负荷。Mac/Linux用户则需安装Python开发包(如GCC)和调试工具(如Windows的Visual Studio自带工具或Mac/Linux的GDB)。
接下来,我们将通过实例创建一个简单的Python扩展模块datetimecpy,模拟官方datetime模块。我们从编写Python调用代码开始,然后用C语言实现,包括头文件引入、定义now方法、注册方法、模块定义、以及将模块嵌入到Python解释器中。
通过本章,你将掌握创建C扩展模块的基础步骤。在后续章节,我们将深入讲解PyObject对象及其在C语言API中的应用。
深入理解 Python 虚拟机:列表(list)的实现原理及源码剖析
深入理解 Python 虚拟机:列表(list)的实现原理及源码剖析
在 Python 虚拟机中,列表作为基本数据类型之一,能够存储各种类型的数据并支持多种操作。本文将详细解析列表在 cpython 实现中的结构和关键操作的源代码。
列表结构解析
在 cpython 实现中,列表由一系列元素构成,每个元素由一个指针指向 Python 对象。列表还包含一个表示元素数量的字段,一个用于存储列表长度的字段,以及一个用于存储对象引用计数的字段。
创建和扩容机制
创建列表时,不会直接分配内存,而是将需要释放的内存地址保存在数组中,以便下次创建列表时复用。列表扩容时,通过检查当前容量并相应地增加,以适应新添加的元素。
插入和删除操作
插入元素时,将插入位置及其后元素后移一位。删除元素时,将后续元素前移,直至空位。
复制操作
列表复制分为浅拷贝和深拷贝。浅拷贝仅复制对象的指针,改变原始列表中的元素会影响复制后的列表。深拷贝则复制对象及其内部内容,确保复制后的列表独立于原始列表。
列表清理和反转
清空列表时,将元素数量字段设置为零,并减少所有对象的引用计数,以便在计数为零时自动释放内存。反转列表使用交换元素指针实现,不改变元素值。
总结
本文深入介绍了 Python 列表的内部实现,包括创建、扩容、插入、删除、复制、清理和反转等操作的源代码。理解这些细节有助于更高效地编写 Python 代码并深入掌握 Python 的内部机制。
python是如何执行的?
理解Python执行,首先需要了解编译型语言的执行过程。以C语言为例,C代码最终会被转换成机器码,由计算机执行。
在Python中,代码会被编译成Python虚拟机可以理解的字节码,然后由Python虚拟机逐条执行字节码。CPython是Python的官方实现,它包含编译部分、虚拟机执行部分、命令行交互式环境、内置模块实现、包安装API等。
Python并非解释型或编译型语言,而是解释型语言。Python代码被编译成字节码,而不是直接生成机器码。字节码由CPython运行,类似于虚拟机。CPython包含了一个用于将Python指令变为字节码指令的编译器、执行字节码的虚拟机,以及命令行交互式解释环境。
Python的编译器将Python代码转换为字节码,通过生成PyCodeObject对象来保存函数调用。每个代码对象包含虚拟机执行的字节码和其他函数信息。使用dis模块的dis方法可以查看一个函数的字节码对应的指令。具体编译过程见Python官方指南。
Python的虚拟机是一个栈机器,字节码解释器通过模拟物理计算机操作多个栈来完成指令。在CPython源码的ceval.c中有一个巨大的switch语句,对应着每一个字节码指令。frame用于保存代码信息和上下文信息,每个函数调用都有一个对应的frame。数据栈/评估栈/值栈是执行指令时的栈。
.pyc文件是Python的缓存信息,用于加速模块加载。.pyc文件包含魔法数字、时间戳和使用marshaled模块序列化的字节码。当导入模块时,Python会检查是否有缓存文件并检查是否过期。如果没有过期,可以绕过编译阶段。最新版本的Python在加载模块时进行了一定流程的判断。
关于Python执行过程的了解,参考了大量资料。虽然无法阅读最新的CPython源码,但仍从各种资料中拼凑出对于Python执行过程的理解。推荐的资料包括官方Python Developer's Guide的CPython内部介绍、CPython源码指南、 Lines or Less A Python Interpreter Written in Python、B站码农高天的深入和清晰的中文讲解。
cpython中的PyObject等对象入门
在 Python 中,一切皆对象,对象的定义对理解程序至关重要。下面,我们从 CPython 的源代码中,介绍 CPython 中基本的对象结构。
在 CPython 中,关于对象的定义主要集中在头文件 Include/object.h 中。在文件的前面部分,可以找到整体的介绍。对象在堆上分配,使用特殊的规则来确保它们能够正确地被垃圾回收。对象不能静态分配或在栈上分配,只能通过特定的宏和函数访问。类型对象是例外,标准类型由静态初始化的类型对象表示,Python 2.2 中的工作使得堆上分配的类型对象成为可能。每个对象都有一个引用计数,当对象的指针被复制或删除时,引用计数会增加或减少。当引用计数达到零时,表示对象不再有任何引用,可以被从堆中移除。每个对象都有一个类型,决定了它代表什么以及包含何种数据类型。对象的类型在创建时固定。类型本身作为对象表示,对象包含指向相应类型对象的指针。类型自身有一个类型指针指向对象代表的类型'类型',该类型包含指向自己的指针!对象在内存中不会漂浮移动,一旦分配,其大小和地址保持不变。需要存储可变大小数据的对象可以包含指向对象可变部分的指针。不同类型的对象不一定具有相同的大小,但分配后大小不能改变。为了使对象的引用可以简单地是一个指针,不允许移动对象或改变对象的大小。对象始终通过 PyObject * 类型的指针访问。 PyObject 是一个只包含引用计数和类型指针的结构。实际分配的对象内存包含其他数据,只能在转换为指向更长结构类型的指针后访问。此更长的类型必须以引用计数和类型字段开始,使用宏 PyObject_HEAD 为这进行(以适应未来的更改)。特定对象类型的实现可以将对象指针转换为正确的类型并返回。
在 CPython 中,最重要的对象是 PyObject,定义在文件 Include/object.h 中。 PyObject_VAR_HEAD 是一个关键的宏,定义在文件 Include/object.h 中。这是一个 PyVarObject,可以简单理解为:
在 Python 中,除了基础的 PyObject 对象之外,还有一些在其基础上扩展的 PyVarObject 对象,因为我们常用的如列表、字典等对象的长度可以随时变化。
每个类型的对象都有一个类型,因此对象的类型数据结构非常重要。它定义在文件 Include/cpython/object.h 中的结构体 _typeobject 中,同时它有一个别名 PyTypeObject,定义如下:
可以看到,结构体 PyTypeObject 相当复杂,下面我们会逐步介绍。
将 PyTypeObject 分为几个部分。
上面的代码中涉及到的第一个关键的宏 PyObject_VAR_HEAD 的定义在文件 Include/object.h 中。这意味着 PyObject_VAR_HEAD 就是一个 PyVarObject,可以简单理解为: