前言 / Introduction

隨著 Python 3.14 的正式發布,多線程開發的限制,也隨著下面的改動迎刃而解:

  • Free-threaded mode (PEP 703),
  • Isolated interpreters (PEP 684),
  • And the new InterpreterPoolExecutor (PEP 734),

Python can now run true parallel CPU-bound code directly — even within the same process.

下面將展示一些 Example

  • Async I/O
  • CPU-bound parallelism
  • Multicore execution with interpreter pools

1. Classic Problem: Async + CPU Work

如果你遇到需要

  • You fetch data from multiple APIs (I/O-bound)
  • Then process, analyze, or compress the data (CPU-bound)

在 Python 3.14 之前

  • asyncio handled I/O efficiently
  • CPU work blocked the event loop
  • You needed multiprocessing or third-party libs

但現在,你可以混用 async + CPU parallelism ,就能清楚的執行。

Example: Async Fetch + CPU Processing (Python 3.14)

import asyncio
from concurrent.futures import InterpreterPoolExecutor
import aiohttp
import hashlib

# CPU-bound task
def compute_hash(data: str):
    h = hashlib.sha256()
    h.update(data.encode("utf-8"))
    return h.hexdigest()

# I/O-bound async task
async def fetch_content(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    urls = [
        "https://httpbin.org/uuid",
        "https://httpbin.org/get",
        "https://httpbin.org/headers",
    ]

    async with aiohttp.ClientSession() as session:
        contents = await asyncio.gather(
            *[fetch_content(session, url) for url in urls]
        )

    # Run CPU-bound processing in parallel interpreters
    with InterpreterPoolExecutor() as executor:
        loop = asyncio.get_running_loop()
        results = await asyncio.gather(
            *[loop.run_in_executor(executor, compute_hash, c) for c in contents]
        )

    print(results)

asyncio.run(main())
  • Fully async I/O
  • True parallel execution for CPU-bound work
  • No multiprocessing boilerplate
  • No shared GIL blocking

2. Parallel CPU Tasks Without Multiprocessing

在 Python 3.14之前,只能透過 multiprocessing.Process or ProcessPoolExecutor 去多核執行,這將涉及 IPC 和 Pickling。

但現在你可以透過 InterpreterPoolExecutor:

from concurrent.futures import InterpreterPoolExecutor

def heavy_calc(n):
    total = 0
    for i in range(n):
        total += (i * i) % 7
    return total

if __name__ == "__main__":
    tasks = [50_000_000, 60_000_000, 70_000_000, 80_000_000]

    with InterpreterPoolExecutor() as executor:
        futures = [
            executor.submit(heavy_calc, size)
            for size in tasks
        ]
        results = [f.result() for f in futures]

    print(results)
  • Runs across multiple CPU cores
  • No GIL contention
  • Same process, cleaner API than multiprocessing

3. Migrating Existing Code

如果你正面臨:

  • ThreadPoolExecutor → No speedup for CPU tasks before
  • multiprocessing → Heavyweight but necessary
  • asyncio → Only useful for I/O

現在你可以逐步地取代舊的方法。

ThreadPoolExecutor (old CPU-bound):

from concurrent.futures import ThreadPoolExecutor
# CPU-bound work = No real speedup

InterpreterPoolExecutor (new and parallel):

from concurrent.futures import InterpreterPoolExecutor
# Runs in parallel across cores

4. Real Use Cases That Now Improve

這邊分享我平時的一些案例:

  • Image Processing
    • Process multiple images in parallel without subprocess overhead.
  • Hashing, Encryption, Compression
    • Perfect match for InterpreterPoolExecutor.
  • Data Science & ETL Pipelines
    • Async I/O + CPU-bound transforms can run together.
  • Log Parsing & Report Generation
    • Parallel parsing while streaming results.
  • Web Scraping + Analysis
    • Use aiohttp + free-threaded CPU workers.

5. What About Libraries and Extensions?

Not all libraries are thread-safe under free-threaded mode yet. But support is growing, especially for:

  • Cython
  • pybind11
  • nanobind
  • PyO3
  • NumPy (ongoing work)

Extension modules will need updates to be fully compatible, but Python 3.14 allows them to adopt free-threading gradually.

6. Should You Switch Now?

Python VersionGIL StatusCPU ParallelismRecommended Use
≤ 3.11Always on❌ NoLegacy / stable only
3.12On⚠️ Prep stageInterpreters isolated
3.13Optional via build✅ YesTest and experiment
3.14Improved + practical✅ YesReal use cases begin

嘗試在一些地方去替換新的 Tools,而不需要全部重寫。

Takeaways

  • Python 3.14 enables true multicore execution using InterpreterPoolExecutor.

  • You can now combine async I/O and parallel CPU tasks in one process.

  • Free-threaded mode (PEP 703) makes threads useful for CPU work.

  • This becomes the practical replacement for multiprocessing in many workloads.

  • Extension libraries are gradually adapting but you can start now.