- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
Python作为一种广泛使用的编程语言,其简洁的语法和强大的功能深受开发者喜爱.
然而,对于许多Python用户来说,CPython(Python的官方实现)的内部工作机制仍然是一个神秘的黑盒.
今天,我们将继续探索CPython的源代码,尝试了解Python从程序启动到字运行的神秘面纱.
CPython的代码库规模庞大,包含约35万行C代码和近60万行Python代码.
这些代码分布在多个目录中,这些目录结构为CPython的开发和维护提供了清晰的组织方式.
主要的目录包括:
Grammar/
:Python语法文件Include/
:头文件Lib/
:标准库模块(Python实现)Modules/
:标准库模块(C实现)Objects/
:内置类型实现。Parser/
:解析器相关代码Programs/
:可执行文件的源码Python/
:解释器核心代码CPython是开源的,代码托管在gihtub上,感兴趣的话,可以下载了查看.
下载了之后,可以切换到自己感兴趣的分支版本.
git clone https://github.com/python/cpython/ && cd cpython git checkout 3.12
编译源码过程相对简单,只需运行以下命令即可:
./configure make make test sudo make install
编译完成后,运行 ./python.exe 即可启动自己编译的CPython版本.
CPython的入口点是 main() 函数,位于 Programs/python.c 文件中.
/* Minimal main program -- everything is loaded from the library */ #include "Python.h" #ifdef MS_WINDOWS int wmain(int argc, wchar_t **argv) { return Py_Main(argc, argv); } #else int main(int argc, char **argv) { return Py_BytesMain(argc, argv); } #endif
这个函数是程序启动的起点,负责初始化CPython并开始执行用户代码.
在Windows平台上,CPython使用 wmain() 作为入口点,以支持UTF-16编码的命令行参数。这种设计使得CPython能够更好地处理不同平台上的字符编码问题.
main()函数的主要职责是调用Py_Main()或Py_BytesMain(),这两个函数分别处理宽字符和字节字符串的命令行参数.
Py_Main和Py_BytesMain位于 Modules/main.c 文件中.
这两个函数进一步调用pymain_main(),开始CPython的初始化过程.
Py_Main,Py_BytesMain以及pymain_main这些函数都在Modules/main.c 文件中.
CPython的初始化过程分为三个阶段:预初始化、核心初始化和主初始化,每个阶段都有其特定的任务和目标.
预初始化阶段主要负责设置运行时状态、默认内存分配器和基本配置.
这一阶段通过调用 _PyRuntime_Initialize() 和 PyPreConfig_InitPythonConfig() 等函数来完成.
这些函数初始化了CPython的全局运行时状态,并为后续的初始化阶段做好了准备.
其中,_PyRuntime_Initialize函数的实现位于:Python/pylifecycle.c 。
PyPreConfig_InitPythonConfig函数的实现位于:Python/preconfig.c 。
核心初始化阶段是CPython初始化的关键部分.
这一阶段初始化了主解释器状态、线程状态、内置类型、 builtins 模块、 sys 模块和导入系统.
这些组件构成了Python运行的核心基础,使得CPython能够开始执行Python代码.
核心初始化通过调用 Py_InitializeFromConfig() 函数来完成,该函数进一步调用了 pyinit_core() 等函数,逐步构建了Python运行时的核心环境.
其中,Py_InitializeFromConfig函数的实现位于:Python/pylifecycle.c 。
主初始化阶段是CPython初始化的最后一步.
这一阶段完成了CPython的全面初始化,包括设置 sys.path 、导入 site 模块等.
这些任务使得CPython能够支持完整的Python功能,包括模块导入和脚本执行.
主初始化通过调用 pyinit_main() 函数来完成,该函数进一步调用了 init_interp_main() 等函数,完成了CPython的最终配置.
其中,pyinit_main和init_interp_main函数的实现位于:Python/pylifecycle.c 。
初始化完成后,CPython进入程序运行阶段。Py_RunMain() 函数(Modules/main.c文件中)是这一阶段的核心,它负责运行Python程序并进行清理.
根据不同的运行模式(如脚本、模块、命令行等), Py_RunMain() 函数调用不同的函数来执行代码.
例如, pymain_run_python() 函数处理 sys.path 的设置和模块的导入,确保Python程序能够在正确的环境中运行.
Python代码的编译和执行是CPython运行的核心部分.
PyRun_FileExFlags()函数(Python/pythonrun.c文件中)是这一过程的入口点,它负责将Python代码编译为字节码,并将其加载到运行时环境中.
编译过程通过调用 _PyAST_Compile() 函数(Python/compile.c文件中)完成,该函数将抽象语法树(AST)编译为代码对象.
最终,PyEval_EvalCode() 函数(Python/pythonrun.c文件中)执行代码对象,进入字节码执行循环.
字节码执行循环是CPython运行的最后阶段.
这一阶段通过调用 _PyEval_EvalFrame() 函数(Include/internal/pycore_ceval.h文件中)来执行字节码指令,_PyEval_EvalFrame() 函数是一个复杂的函数,它负责处理各种Python操作,包括函数调用、变量访问和异常处理等.
如果想更好地理解Python的运行机制,可以深入研究这个函数.
本文主要从CPython源代码的角度来了解Python程序从启动到执行的全过程.
源代码是基于CPyhton 3.12 分支的.
通过阅读和分析CPython的源代码,我们不仅能够更好地理解Python的内部机制,还能够发现优化和改进的机会.
如果对CPython的内部工作机制感兴趣,最好能够亲自探索其源代码。通过阅读和理解源代码,将获得更深入的知识,并能够更好地利用Python的强大功能.
最后此篇关于『Python底层原理』--CPython如何运行Python代码的文章就讲到这里了,如果你想了解更多关于『Python底层原理』--CPython如何运行Python代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
Bài viết này khám phá toàn diện và sâu sắc về công nghệ giao tiếp container Docker, từ các khái niệm cơ bản, mô hình mạng, thành phần cốt lõi đến các ứng dụng thực tế. Bài báo này giới thiệu chi tiết các chế độ mạng khác nhau và cách triển khai chúng, cung cấp thông tin chi tiết về kỹ thuật và các trường hợp thực tế về giao tiếp container, đồng thời hướng đến mục tiêu cung cấp hiểu biết sâu sắc về kỹ thuật và kinh nghiệm thực tế cho các chuyên gia.
Trang chủ blog: Một người ủng hộ công nghệ học tập ngày nay mang đến cho bạn một bài viết có tên là "Bắt đầu nhanh với Dubbo - Giúp bạn hiểu được cách sử dụng và nguyên lý của Dubbo" Tôi hy vọng rằng tất cả bạn bè của tôi có thể kiên nhẫn đọc bài viết này. Người viết blog cũng đang trong giai đoạn học tập.
1. Như đã đề cập ở trên, chúng ta thường sử dụng npm install, nhưng bạn đã bao giờ nghĩ về các nguyên tắc bên trong của nó chưa? 1. Thực hiện npm install. Nó giúp chúng ta thực hiện được điều gì ở hậu trường? 2. Chúng ta sẽ thấy rằng có một gói khác-lo
Base64 Base64 là gì? Đây là thuật toán chuyển đổi luồng byte thành các ký tự có thể in và chuyển đổi các ký tự có thể in thành luồng byte. Base64 sử dụng 64 ký tự có thể in được để biểu diễn dữ liệu đã chuyển đổi. Nói một cách chính xác thì Base64 không được tính
Nội dungĐịnh nghĩa CoroutineGenerator và Yield SemanticsFuture ClassIOLoop Classcoroutine Function DecoratorSummarytornado
Slice, đây là một khái niệm mới được giới thiệu trong ngôn ngữ Go. Nó có một số tính năng như sau: Mảng trừu tượng Độ dài của mảng không cố định và các phần tử có thể được thêm vào Dung lượng lát cắt có thể được tăng lên Dung lượng tăng lên trong các lát cắt Trước tiên, hãy sắp xếp các khái niệm trên tại đây
Nguồn: https://sourl.cn/HpZHvy Giới thiệu Bài viết này chủ yếu thảo luận về "nguyên tắc triển khai RPC", vì vậy trước hết, chúng ta hãy làm rõ câu hỏi: RPC là gì? RPC là Remote Procedure Call
Địa chỉ mã nguồn (bao gồm tất cả các thiết lập liên quan đến springmvc, đường dẫn tệp tĩnh, chấp nhận tham số đầu vào yêu cầu, thiết lập bộ chuyển đổi xử lý giá trị trả về, v.v.): spring-framework/WebMvcConfiguration
Vui lòng cho tôi xem một ví dụ nhỏ về nguyên lý tiêm phụ thuộc thông qua lớp Java đơn giản. Mặc dù tôi đã hiểu Spring nhưng nếu tôi cần giải thích bằng các thuật ngữ lớp Java đơn giản thì bạn có thể cho tôi xem một ví dụ đơn giản không? Cảm ơn trước.
1. Bối cảnh Chúng ta thường sử dụng điện thoại di động và máy tính để lướt Internet và cần truy cập tài nguyên mạng trên Internet công cộng, chẳng hạn như duyệt Taobao và xem video. Vậy làm thế nào để điện thoại di động và máy tính biết nơi để lấy các tài nguyên mạng này và tải xuống cục bộ? Ví dụ, khi tôi đến căng tin để lấy thức ăn, tôi cần
Xin chào mọi người, tôi là Fei Ge! Hiện nay ứng dụng của công cụ iptables dường như đang ngày càng trở nên phổ biến hơn. Nó không chỉ xuất hiện trong tường lửa truyền thống, NAT và các chức năng khác mà còn xuất hiện trong các dự án Docker, Kubernets và Istio phổ biến hiện nay.
Tất cả các giao diện liên quan đến bài viết này đều không có trong tài liệu công khai. Bạn cần tải xuống mã nguồn trên GitHub và tự tạo tài liệu cho lớp riêng tư. npm run generateDocumentation -- --private yarn gene
Gần đây tôi nhận thấy trong rất nhiều mã, mọi người đặt các giá trị cấu hình được mã hóa cứng (như số cổng, v.v.) sâu trong các lớp/phương thức, khiến chúng khó tìm và không thể cấu hình. Điều này có vi phạm nguyên tắc SOLID không? Nếu không, có “nguyên tắc” nào khác mà tôi có thể trích dẫn cho các thành viên trong nhóm để giải thích lý do không?
Tôi mới làm quen với C#, WPF và mô hình MVVM. Xin lỗi vì bài viết dài, tôi đã cố gắng trình bày tất cả những điểm tôi hiểu (hoặc không hiểu). Sau khi nghiên cứu rất nhiều văn bản về cơ chế lệnh và mô hình MVVM do WPF cung cấp, tôi đã cố gắng tìm ra cách sử dụng điều này
Hàm jQuery tương tự $.post("/example/handler", {foo: 1, bar: 2}); sẽ tạo một yêu cầu với tham số post foo=1&bar=2. Cho $htt
Vấn đề chính là gì nếu Django không sử dụng nguyên tắc "thực thi truy vấn bị trì hoãn"? q = Entry.objects.filter(headline__startswith="What") q = q.filter(
Hôm nay tôi phát hiện ra rằng .NET framework tuân theo thứ tự hoạt động BODMAS khi thực hiện tính toán. tức là các phép tính được thực hiện theo thứ tự sau: Dấu ngoặc Thứ tự Chia Nhân Cộng Trừ Tuy nhiên, tôi đã tìm kiếm xung quanh và không thể tìm thấy bất kỳ tài liệu nào xác nhận rằng .NET thực sự tuân theo thứ tự này, có tài liệu nào như vậy không? giống
Hoàn thành. Câu hỏi này không đáp ứng được hướng dẫn của Stack Overflow. Hiện tại câu hỏi này không chấp nhận câu trả lời. Chúng tôi không cho phép những câu hỏi yêu cầu giới thiệu sách, công cụ, thư viện phần mềm, v.v. Bạn có thể chỉnh sửa câu hỏi để có thể trả lời bằng các sự kiện và trích dẫn. đóng cửa
Đánh giá API Khi tạo Viewer, bạn có thể trực tiếp chỉ định nhà cung cấp hình ảnh (ImageryProvider). Bản chính thức cung cấp một ví dụ rất đơn giản, đó là ví dụ ngoài màn hình (tìm kiếm ngoại tuyến): new Cesium.Viewer(
Theo tình hình hiện tại, câu hỏi này không phù hợp với định dạng Hỏi & Đáp của chúng tôi. Chúng tôi mong đợi câu trả lời sẽ là
Tôi là một lập trình viên xuất sắc, rất giỏi!