<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Python 3.14 on KbWen Blog</title>
    <link>https://www.kbwen.com/tags/python-3.14/</link>
    <description>KbWen is a practical technology blog about AI systems, machine learning, Python, data engineering, and software development.</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <image>
      <url>https://www.kbwen.com/images/og-default.png</url>
      <title>KbWen Blog</title>
      <link>https://www.kbwen.com/</link>
    </image>
    
    <lastBuildDate>Thu, 10 Sep 2026 09:15:00 +0800</lastBuildDate><atom:link href="https://www.kbwen.com/tags/python-3.14/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Python 3.14 的 free-threading build</title>
      <link>https://www.kbwen.com/python-free-threading-no-gil/</link>
      <pubDate>Thu, 10 Sep 2026 09:15:00 +0800</pubDate><dc:creator>KbWen</dc:creator>
      <guid>https://www.kbwen.com/python-free-threading-no-gil/</guid>
      <description>Python 3.14 起 free-threading build 正式支援，GIL 可以在執行期關掉。這篇說明 GIL 原本負責什麼、怎麼判斷使用的 python 有沒有真的關掉 GIL，以及關掉之後單執行緒與 C 擴充套件相容性的影響。</description>
      <content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR</strong>：想確認 python 有沒有真的關掉 GIL，跑 <code>python -VV</code> 看是不是 free-threading build，import 完所有套件之後跑 <code>sys._is_gil_enabled()</code>（3.13 起才有），輸出是 <code>False</code> 才代表這次執行真的沒有 GIL。3.14 起 free-threading 正式支援、但目前還不是預設項目；關掉 GIL 的影響是單執行緒變慢，以及沒支援的 C 擴充套件一被匯入就會把 GIL 重新開起來。</p>
</blockquote>
<p>Python 3.14 起，free-threading build 從實驗性變成正式支援。這類的 build 可以在不啟用 GIL 的情況下跑 Python 程式，執行檔通常叫 <code>python3.14t</code>，跟一般的 <code>python3.14</code> 並存。GIL 拿掉之後，多執行緒才可能真的同時執行 Python；但拿掉 GIL，也會影響其他地方。</p>
<h2 id="gil">GIL</h2>
<p>GIL 是 CPython 的全域直譯器鎖，作用是不讓多個執行緒同時執行 Python 程式（PEP 703 說明 prevents multiple threads from executing Python code at the same time）。它的核心理由跟記憶體管理相關。CPython 靠參考計數回收物件，每當有變數指到或不再指到某個物件，那個物件的計數就要加一或減一；而在有 GIL 的前提下，同一時間只有一個執行緒在跑。</p>
<p>要拿掉 GIL，這套邏輯作法就會不一樣。PEP 703 提的做法之一，是把原本非原子的參考計數換成 biased reference counting 這種執行緒安全的計數方式（a switch from plain non-atomic reference counting to biased reference counting）。實作細節這邊不討論，重點的差別是 GIL 換來的其實是「參考計數不必加鎖」；如果拿掉，就得在計數機制上把執行緒安全補回來。</p>
<h2 id="314起正式支援">3.14起正式支援</h2>
<p>3.13 一開始加入 free-threading 時還是實驗性的。到 3.14 就變成正式性質，&ldquo;The free-threaded build of Python is now supported and no longer experimental&rdquo;。對應的規範是 PEP 779，它替「轉到正式支援」這個階段訂定出明確的條件（requirements for moving to Phase II, making the free-threaded Python build officially supported）。</p>
<p>但是正式支援不等於預設。整件事分成幾個階段：Phase II 讓 free-threaded build 變成官方支援、但仍然是選用的，要到 Phase III 才會讓它成為預設（officially supported but still optional, and phase III would make the free-threaded build the default）。以目前的資料看，裝好標準的 python3.14，預設仍然是 GIL 的版本，要 free-threading 得另外取得 free-threading build。</p>
<h2 id="判斷狀態build執行期">判斷狀態：build、執行期</h2>
<p>這是最容易搞混的地方，因為要分兩個地方看。</p>
<p>第一，是安裝的 python 本身支不支援 free-threading。直接跑 <code>python -VV</code>，輸出的版本資訊裡如果寫著 free-threading build，就是支援的 build。程式內也可以查詢編譯設定：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sysconfig</span>
</span></span><span class="line"><span class="cl"><span class="n">sysconfig</span><span class="o">.</span><span class="n">get_config_var</span><span class="p">(</span><span class="s2">&#34;Py_GIL_DISABLED&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>回 <code>1</code> 代表這個 build 支援 free threading（then the build supports free threading），回 <code>0</code> 或 <code>None</code> 就是一般的帶 GIL build。</p>
<p>第二，是這次執行到底有沒有真的把 GIL 關掉。3.13 起有個函式可以查詢：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="cl"><span class="n">sys</span><span class="o">.</span><span class="n">_is_gil_enabled</span><span class="p">()</span>
</span></span></code></pre></div><p>如果回 <code>False</code> 才代表這次跑起來 GIL 是關的（HOWTO：can be used to check whether the GIL is actually disabled in the running process）。那你可能會想支援的 build 為什麼還開著 GIL？有兩種情況。一種是明確要求：設環境變數 <code>PYTHON_GIL=1</code>，或啟動時加 <code>-X gil=1</code>，都會把 GIL 開回來（反過來 <code>PYTHON_GIL=0</code> 或 <code>-X gil=0</code> 是關）。另一種比較隱性、也比較常遇到：匯入沒有標記支援 free-threading 的 C 擴充套件時，直譯器會自動把 GIL 重新開起來。</p>
<p>隱性最值得被記住，因為它會讓兩個地方對不起來：build 明明支援，<code>sys._is_gil_enabled()</code> 卻回 True。所以要確認就要把查詢寫在 import 完所有套件之後跑，而不是一開機、還沒載入依賴就執行。</p>
<h2 id="關掉之後">關掉之後</h2>
<p>效能上，關掉 GIL 會讓單執行緒的程式變慢，因為參考計數改成執行緒安全的版本、以及其他為了無鎖並行做的調整。這裡有兩組官方數字，What&rsquo;s New 3.14：單執行緒的效能損失目前大約落在 5 到 10%，會隨平台和 C 編譯器而變（roughly 5-10%）。HOWTO 則是 pyperformance 的實測範圍，平均開銷從 macOS aarch64 上約 1%，到 x86-64 Linux 上約 8%（the average overhead ranges from about 1% on macOS aarch64 to 8% on x86-64 Linux systems）。大家真的想知道可以實際量測差別，以及自己開發產品的類型來決策。</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
