March 26, 20268 min read

Python 3.13 — New Features Every Developer Should Know

What's new in Python 3.13 — the new REPL, free-threaded mode, experimental JIT compiler, improved error messages, and deprecations you need to handle.

python 3.13 new features update programming
Ad 336x280

Python 3.13 shipped in October 2024 with two changes that have been requested for over a decade: an experimental free-threaded mode that removes the GIL, and an experimental JIT compiler. Neither is production-ready yet — both are marked experimental — but they signal the direction Python is heading. Beyond the headlines, 3.13 brings a significantly improved REPL, better error messages, typing improvements, and deprecation removals that might break your code.

The New REPL

The interactive Python shell got its first major overhaul in years. If you spend any time in python3 for testing snippets, this matters.

# The new REPL supports:
# - Multi-line editing (arrow keys work across lines)
# - Syntax highlighting (colored output)
# - Paste mode (paste multi-line code without indentation issues)
# - History browsing with up/down through multi-line blocks
# - Automatic indentation for blocks

>>> def fibonacci(n):
... if n <= 1:
... return n
... return fibonacci(n - 1) + fibonacci(n - 2)
...
>>> # You can now arrow-up and edit the entire function
>>> # Previously, up-arrow only recalled one line at a time

The new REPL uses color by default. Keywords are colored, strings are colored, and error tracebacks are colored and more readable. This was previously only available through IPython or ptpython.

# Tracebacks are now colored and more informative
>>> data = {"users": [{"name": "Alice"}]}
>>> data["users"][0]["email"]
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    data["users"][0]["email"]
    ~~~~~~~~~~~~~~~~~~~^^^^^^^
KeyError: 'email'

The ^^^^^^^ indicator pointing at exactly which key lookup failed has been improving since 3.11, and 3.13 continues that trend.

Free-Threaded Mode (Experimental)

This is the big one. Python's Global Interpreter Lock (GIL) has been the elephant in the room for CPU-bound parallelism since forever. Python 3.13 introduces an experimental build without the GIL.

# Install the free-threaded build (separate from standard Python)
# On macOS with Homebrew:
brew install python@3.13 --with-freethreaded

# Or using pyenv:
pyenv install 3.13t  # 't' suffix = free-threaded

# Check if GIL is disabled
python3.13t -c "import sys; print(sys._is_gil_enabled())"
# False
What this means in practice:
# With the GIL (standard Python), threads can't run CPU-bound code in parallel
# Without the GIL (free-threaded), true parallelism is possible

import threading
import time

def cpu_bound_work(n):
"""Simulate CPU-intensive computation"""
total = 0
for i in range(n):
total += i * i
return total

# Standard Python 3.13: ~4 seconds (threads run sequentially for CPU work) # Free-threaded Python 3.13t: ~1 second (threads run in parallel) start = time.time() threads = [] for _ in range(4): t = threading.Thread(target=cpu_bound_work, args=(10_000_000,)) threads.append(t) t.start()

for t in threads:
t.join()

print(f"Elapsed: {time.time() - start:.2f}s")

Important caveats:
  • This is experimental. Many C extensions aren't thread-safe without the GIL. NumPy, pandas, and most scientific computing libraries need updates.
  • It's a separate build — you install python3.13t alongside python3.13.
  • Single-threaded performance is ~5-10% slower without the GIL due to the overhead of fine-grained locking.
  • The Python core team says this won't be the default until 3.15 or later, if ever.
For most developers right now: Keep using the standard build. The free-threaded mode is for experimentation and for C extension authors to start adapting their code.

Experimental JIT Compiler

Python 3.13 includes a "copy-and-patch" JIT compiler as a build-time option. It's off by default and not included in standard builds.

# Build Python with JIT enabled (compile from source)
./configure --enable-experimental-jit
make

# Or set environment variable for JIT-enabled builds
PYTHON_JIT=1 python3.13 my_script.py

The JIT translates Python bytecode into machine code at runtime. In benchmarks, it shows 2-9% performance improvement on pyperformance. That's modest, but it's the foundation for more aggressive optimizations in future releases.

This is a long-term investment. Don't expect dramatic speedups now — the architecture enables future gains.

Improved Error Messages

Python has been steadily improving error messages since 3.10, and 3.13 continues the trend.

# Better NameError suggestions
>>> import colections
Traceback (most recent call last):
  ...
ModuleNotFoundError: No module named 'colections'. Did you mean: 'collections'?

# Better suggestions for common mistakes
>>> color = "red"
>>> colour
Traceback (most recent call last):
  ...
NameError: name 'colour' is not defined. Did you mean: 'color'?

# Improved SyntaxError for missing commas in collections
>>> data = [
...     "alice"
...     "bob"
... ]
SyntaxError: invalid syntax. Perhaps you forgot a comma?
# Better error for invalid escape sequences (now a warning since 3.12, SyntaxWarning)
>>> path = "C:\new\folder"
SyntaxWarning: invalid escape sequence '\n'
SyntaxWarning: invalid escape sequence '\f'
# In 3.13, these become errors by default in some contexts

# Fix: use raw strings or escaped backslashes
>>> path = r"C:\new\folder"      # Raw string
>>> path = "C:\\new\\folder"     # Escaped backslashes

Typing Improvements

# typing.ReadOnly for TypedDict fields (PEP 705)
from typing import TypedDict, ReadOnly

class User(TypedDict):
id: ReadOnly[int] # Cannot be modified after creation
name: str # Mutable
email: str # Mutable

def update_user(user: User) -> None:
user["name"] = "Alice" # OK
user["id"] = 42 # Type error — ReadOnly field

# typing.deprecated decorator (PEP 702) from typing import deprecated

@deprecated("Use calculate_v2() instead")
def calculate(x: int) -> int:
return x * 2

calculate(5) # Type checkers show a deprecation warning

# Improved TypeVar defaults (PEP 696)
from typing import TypeVar

T = TypeVar("T", default=str)

class Container[T = str]: # Default type parameter
def __init__(self, value: T) -> None:
self.value = value

c1 = Container("hello") # Container[str]
c2 = Container(42) # Container[int]
c3: Container = Container("text") # Defaults to Container[str]

Dead Batteries Removed

Python 3.13 removes several modules that were deprecated in 3.11 (PEP 594). If your code imports any of these, it will break:

# These modules are GONE in 3.13
import aifc          # Removed
import audioop       # Removed
import cgi           # Removed — use urllib.parse instead
import cgitb         # Removed
import chunk         # Removed
import crypt         # Removed — use hashlib or bcrypt
import imghdr        # Removed — use Pillow or python-magic
import mailcap       # Removed
import msilib        # Removed
import nis           # Removed
import nntplib       # Removed
import ossaudiodev   # Removed
import pipes         # Removed — use subprocess
import sndhdr        # Removed
import spwd          # Removed
import sunau         # Removed
import telnetlib     # Removed — use telnetlib3
import uu            # Removed
import xdrlib        # Removed
The most common breakage: cgi and imghdr. If your web app uses cgi.parse_header() or cgi.FieldStorage, you need to migrate. For cgi.parse_header(), the email module has equivalent functionality:
# Before (3.12 and earlier)
import cgi
content_type, params = cgi.parse_header("text/html; charset=utf-8")

# After (3.13+)
from email.message import Message
m = Message()
m["content-type"] = "text/html; charset=utf-8"
content_type = m.get_content_type()   # "text/html"
charset = m.get_param("charset")       # "utf-8"

Other Notable Changes

# copy.replace() — generic copy-and-modify (PEP 667)
import copy

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
x: float
y: float
z: float = 0.0

p1 = Point(1.0, 2.0, 3.0)
p2 = copy.replace(p1, z=10.0) # Point(x=1.0, y=2.0, z=10.0)

# Also works with datetime, namedtuple, and any class # implementing __replace__
# Improved dbm module — defaults to dbm.sqlite3
import dbm

# In 3.13, the default backend is SQLite instead of platform-dependent choices
with dbm.open("mydata", "c") as db:
    db["key"] = "value"
    print(db["key"])
# pathlib improvements
from pathlib import Path, PurePosixPath

# New: full_match() for shell-style pattern matching
path = Path("/home/user/documents/report.pdf")
path.full_match("*/.pdf")        # True
path.full_match("/home/*/.txt")  # False

# New: from_uri() class method
p = PurePosixPath.from_uri("file:///home/user/data.csv")

Should You Upgrade?

Upgrade now if:
  • You want the improved REPL, error messages, and typing features
  • Your test suite passes (run it first)
  • You don't depend on removed modules
Wait if:
  • You depend on C extensions that haven't tested with 3.13
  • You use cgi, imghdr, or other removed modules and haven't migrated
  • You need maximum stability for production deployments (give it a few point releases)
Ignore the GIL removal and JIT for now. They're experimental, off by default, and not ready for production use. They're research previews of Python's future, not tools for today.
# Test your project against 3.13
python3.13 -m pytest
# or
python3.13 -m py_compile your_script.py

# Check for removed module usage
grep -r "import cgi\|import imghdr\|import telnetlib" your_project/

Python 3.13 is a solid release. The REPL improvements alone make the daily development experience better, and the typing additions continue making Python more suitable for large codebases. The GIL removal and JIT are futures worth watching. For more Python guides and language comparisons, explore CodeUp.

Ad 728x90