Category: Python-internals
-
Why python 2: negative number cannot be raised to a fractional power, but work on Python 3
問題是這個樣子的 [crayon-65183a7685eba690500479/] 為什麼會有 Python 2 不能運算 (-1) ** .5 而 Python 3 可以的狀況?直覺想就是 Python 2 的 integer __pow__ 並沒有支援 pow 運算轉型為 Complex,而在 Python 3 中會轉行為 Complex。但是要怎麼驗證這個行為? 編譯 CPython 並且使用 gdb 追蹤 根據以前接觸 CPython 的狀況,總之找出 object slot function 後就能夠設定斷點追蹤,以這個例子而言,在 Python 2 是 Object/intobject.c:int_pow 承接,Python 3 則是 Object/longobject.c:long_pow 承接。(至於 Python 2 是 intobject, Python 3 卻改成 longobject 的原因,這又是另一個故事了)。 找出需要斷點的地方後,先把 CPython […]
-
Diagnosing and Fixing Reference Leaks in CPython
CPython's garbage collection relies on each object's reference count. Each object has their own reference count, when the object is referenced by others, then we will need to increase object's reference count by the Py_INCREF macro. In another way, when the referencer don't need the object anymore, it will need to decrease object's reference count by the Py_DECREF macro. When object's […]
-
深入 GIL: 如何寫出快速且 thread-safe 的 Python - Grok the GIL: How to write fast and thread-safe Python
本文將會探討 Python 內部的 Global Interpreter Lock,以及學習其如何影響 multi-threaded 程式。 原作者:A. Jesse,Twitter: @jessejiryudavis 原文:Grok the GIL: How to write fast and thread-safe Python Louie Lu 經作者同意[1][2]翻譯為正體中文。 當我6歲時,我有一個音樂盒。我將他上緊發條,在上面的芭蕾舞者開始繞圈,而盒子內的機關開始敲打,發出「一閃一閃亮晶晶」的聲音。雖然這東西肯定很廉價,不過我喜歡這個音樂盒,而我想要知道他是怎麼運作的。總之,我打開了這個音樂盒,看到了裏面的裝置 ── 一個我拇指大小的金屬圓筒,安裝得當的讓他可以旋轉,透過凸起的牙齒與鋼梳撞擊後發出音符。 在程式設計師的特點中,關於事情如何運作的好奇心是必不可缺的。當我打開我的音樂盒觀看內部時,我展現我可能是一個 ── 如果不是一個頂尖程式設計師 ── 起碼也會是好奇的一個。 這很奇怪,我在對 Global Interpreter Lock (GIL) 誤解的情況下寫了 Python 程式這麼久,因為我還沒有足夠的好奇心來了解他是如何運作的。我遇到很多人跟我有著同樣的猶豫,以及無知。 該是時候把這個黑盒子翹開了。讓我們閱讀 CPython 原始碼來了解什麼是 GIL,為什麼 Python 會有,以及他是如何影響我們撰寫 multi-threaded 程式。我會給出一些範例來讓你了解 GIL。你會學到如何快速寫出 thread-safe 的 Python,以及如何在 threads 與 processes 之間選擇。 […]
-
Python Libs - Why "profile" can't be context manager?
Why Python standard library "profile" can't be context manager like this [crayon-65183a7686ea1667981891/] Zero, what is "profile" module in Python? According to Python 3 Documentation: profile, a pure Python module whose interface is imitated by cProfile, but which adds significant overhead to profiled programs. If you’re trying to extend the profiler in some way, the […]
-
Python 底層運作 02 - PyTokenizer_Get 分析
當 Python 在讀入程式碼的時候, 第一步就是對程式碼 lexing,將程式碼拆解成 token,標記出每個元素的分類為何。 以下面的程式碼為例: [crayon-65183a7687152483525088/] 我們透過 tokenize module 來分析,會變成: [crayon-65183a7687157836009082/] 我們可以看到 foo 被標記為 NAME,= 標記為 OP (operator),12345 則被標記為 NUMBER。 在 CPython 中,負責將程式碼標記成 token 的程式碼是 PyTokenizer_Get ,位於 Parser/tokenizer.c。PyTokenizer_Get 本身是 tok_get 的一個 wrapper,用來處理 decoding error 的 handling;其回傳值是該 token 的類別,這些類別的值在 Include/token.h 以 macro 的方式被定義出來;p_start 以及 p_end 則是該 token 的起始以及結束位置: [crayon-65183a7687159202831994/] [crayon-65183a768715b338040045/] 主要的處理集中在 tok_get 當中,這個 function 的目的是要獲得下一個 token,並且會將空白 strip 掉。 整段 tok_get 的 function code […]
-
Python 底層運作 01 - 虛擬機器與 Byte Code
你可曾想過這段 Python 程式碼是如何運作的? [crayon-65183a76873d2011566280/] Python 作為 interpreted language,其運作可以分為兩個大項,Compiler 以及 Virtual Machine。Compiler 負責將輸入的語法做分析,轉換成 AST (Abstract Syntax Tree),再轉換成 CFG,最後依照 CFG 輸出 bytecode,Code Object 等必要的物件。Virtual Machine 則根據 bytecode 來運行,最後輸出程式運行的結果。 我們可以透過 Python 的 dis 模組,來得知程式碼的 Byte Code 是什麼: [crayon-65183a76873d7534819431/] 詳細的 Byte Code 資訊可以到 32.12 dis - Disassembler for Python bytecode 第一行 a = 5 對應的是 LOAD_CONST 以及 STORE_NAME 這兩個 bytecode,透過 LOAD_CONST 將 const 放置到 stack top,接著 […]