CPython开启自毙之旅

本文详细介绍了Python C扩展的源码结构,特别是PyObject和PyTypeObject结构体,探讨了引用计数、类型定义以及C编写的性能关键模块。通过阅读_CPython源码,了解Python内部如何处理对象和类型,包括内存管理、方法实现等核心概念。

首先啊,我只学过C. 其次,我只在大一的时候学过C. 最后,我更爱Rust.

但是我也很喜欢Python。 所以说,自虐吧, CPython源码阅读计划开启:

参考博客:https://www.cnblogs.com/traditional/p/13655426.html

我们可以import调用,但是在Python安装目录里面则是看不到的。像这种底层由C编写、内嵌在解释器里面的模块,以及那些无法使用文本打开的pyd文件,pycharm都会给你做一个抽象,并且把注释给你写好。

Python源码中的Modules目录,这个目录里面存放了大量使用C编写的模块,我们在编译完Python之后就,这些模块就内嵌在解释器里面了。而这些模块都是针对那些性能要求比较高的,而要求不高的则由Python编写,存放在Lib目录下。像我们平时调用random、collections、threading,其实它们背后会调用_random、_collections、_thread。再比如我们使用的re模块,真正用来做正则匹配的逻辑实际上位于 *Modules/_sre.c* 里面而跟编译器相关的一些头文件一般都在Include文件夹下面。核心代码在Include/internal下面的哪些头文件中定义了主要的数据结构,看了一天好不容易捋了捋文件的脉络,太不容易了呜呜呜。

先了解一些基本文件: Include/pytypedefs.h 等量定义了超级一部分的Python模块对象,新的Py打头的结构体优先考虑在这里面寻找

类:

首先看看Python对象的核心PyObject:

// 在pytyprdefs.h 文件中使用typeof做了等价定义,也就是Pyobjects与_object等价
typedef struct _object PyObject;
typedef struct _typeobject PyTypeObject;

//(Include/) object.h
struct _object {
   
   
    _PyObject_HEAD_EXTRA    // 这是一个宏定义的相当于Null或两个,两个(指向前面和后面) PyObject/self结构体的指针
    Py_ssize_t ob_refcnt;   // 垃圾回收机制的引用计数器,一个有符号整形
    PyTypeObject *ob_type;  // 类的类型定义
};

// 第一个参数宏的定义:
// 如果定义了说明之前使用过相同的类,参考https://blog.youkuaiyun.com/weixin_42511320/article/details/106037958
// 在Python中创建的所有类都会放进refchain的环(双向链表)中。在只有一个类或没有类的时候不需要前后指针,但是一旦由两个以上的类的时候就要用指针吧这些类连起来
// 
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA            \
// 定义两个指针,一个指向前一个定义的类,一个指向后一个定义的类(双向链表)
    PyObject *_ob_next;           \
    PyObject *_ob_prev;

07-16
CPythonPython 编程语言的参考实现,它是一个开源项目,主要由 C 语言编写而成。CPython 负责将 Python 源代码编译为字节码,并在虚拟机中执行这些字节码指令。它是 Python 生态系统中最广泛使用的解释器[^1]。 ### 解释器架构 CPython 的核心架构包括以下几个关键组件: - **词法分析器(Lexer)**:负责将字符序列转换为标记(tokens),这是解析过程的第一步。 - **语法分析器(Parser)**:接收来自词法分析器的标记,并根据 Python 的语法规则构建抽象语法树(AST)。 - **编译器**:将 AST 转换为字节码,这是一种低级的、与平台无关的表示形式。 - **虚拟机(VM)**:也称为解释器循环,负责执行字节码。CPython 使用一个基于栈的虚拟机来执行指令。 ### 全局解释器锁 (GIL) CPython 实现了一个重要的特性——全局解释器锁(Global Interpreter Lock, GIL)。GIL 是一种互斥锁,它保护对 Python 对象的访问,防止多个线程同时执行 Python 字节码。这意味着即使在多核处理器上,CPython 的多线程程序也无法利用多核的优势来提高 CPU 密集型任务的性能。然而,对于 I/O 密集型任务,多线程仍然可以带来性能提升,因为线程可以在等待 I/O 操作完成时释放 GIL。 ### 内存管理 CPython 使用了一种自动内存管理系统,其中包括垃圾回收机制。Python 的内存管理器负责分配和释放内存,开发者通常不需要手动管理内存。CPython 的垃圾回收器主要处理循环引用的问题,即当对象之间相互引用时,无法通过简单的引用计数机制来释放内存。为此,CPython 引入了 `gc` 模块,提供了一个可配置的垃圾回收接口。 ### 扩展性 CPython 支持通过扩展模块来增强其功能。这些扩展模块可以用 C 或 C++ 编写,并且可以通过 Python 的 API 与 Python 代码交互。这种能力使得 CPYthon 可以轻松地集成现有的 C/C++ 库,从而提高性能或访问底层系统资源。例如,NumPy 和 Pandas 这样的科学计算库就大量使用了 C 扩展来优化性能[^1]。 ### 示例代码:创建一个简单的 C 扩展 下面是一个简单的例子,展示了如何创建一个 C 扩展模块,该模块提供了一个函数用于计算两个整数的和: ```c #include <Python.h> static PyObject* add_numbers(PyObject* self, PyObject* args) { int a, b; if (!PyArg_ParseTuple(args, "ii", &a, &b)) { return NULL; } return Py_BuildValue("i", a + b); } static PyMethodDef module_methods[] = { {"add_numbers", add_numbers, METH_VARARGS, "Add two integers."}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef cmod = { PyModuleDef_HEAD_INIT, "mymodule", "A simple module to add numbers.", -1, module_methods }; PyMODINIT_FUNC PyInit_mymodule(void) { return PyModule_Create(&cmod); } ``` 为了编译这个模块,你需要使用 distutils 工具链,创建一个 setup.py 文件并运行相应的命令。一旦成功编译安装,就可以像普通 Python 模块一样导入和使用它[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值