Overview
Python 3.2, released on February 20, 2011, is a feature-rich release. It introduces argparse to replace optparse, the concurrent.futures module to simplify parallel programming, and defines a stable ABI for C extensions.
This version also marks the arrival of functools.lru_cache, a caching decorator that would quickly become indispensable. With these additions, Python 3.2 establishes itself as a mature release of the 3.x branch.
Major Features
argparse
The argparse module replaces optparse for command-line argument processing. It supports subcommands, type validation, mutually exclusive arguments, and automatic help generation.
import argparse
def create_parser():
"""Create a CLI tool for file management."""
parser = argparse.ArgumentParser(
description="CSV data processing tool"
)
# Required positional argument
parser.add_argument("file", help="Path to the CSV file")
# Options with types and default values
parser.add_argument(
"-d", "--delimiter",
default=",",
help="Column delimiter (default: comma)"
)
parser.add_argument(
"-n", "--num-lines",
type=int,
default=10,
help="Number of lines to display"
)
# Subcommands
subparsers = parser.add_subparsers(dest="command")
# 'summarize' subcommand
sp_summarize = subparsers.add_parser("summarize", help="Show a summary")
sp_summarize.add_argument(
"--columns",
nargs="+",
help="Columns to include in the summary"
)
# 'convert' subcommand
sp_convert = subparsers.add_parser("convert", help="Convert the format")
sp_convert.add_argument(
"--format",
choices=["json", "xml", "yaml"],
required=True,
help="Output format"
)
return parser
# Usage:
# python tool.py data.csv -n 5 summarize --columns name age
# python tool.py data.csv convert --format json
concurrent.futures
The concurrent.futures module provides a unified, high-level interface for executing tasks in parallel, whether using threads (ThreadPoolExecutor) or processes (ProcessPoolExecutor). Its future-based API greatly simplifies concurrent programming.
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import urllib.request
import time
# --- Example with ThreadPoolExecutor: parallel downloads ---
urls = [
"https://www.python.org",
"https://pypi.org",
"https://docs.python.org",
"https://peps.python.org",
]
def download(url):
"""Download a page and return its size."""
start = time.time()
with urllib.request.urlopen(url, timeout=10) as response:
content = response.read()
duration = time.time() - start
return url, len(content), duration
# Download in parallel with 4 threads
with ThreadPoolExecutor(max_workers=4) as executor:
results = executor.map(download, urls)
for url, size, duration in results:
print(f"{url}: {size} bytes in {duration:.2f}s")
# --- Example with ProcessPoolExecutor: CPU-intensive work ---
def is_prime(n):
"""Check if a number is prime."""
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
numbers = [15485863, 15485867, 32452843, 32452867]
with ProcessPoolExecutor() as executor:
futures = {executor.submit(is_prime, n): n for n in numbers}
for future in futures:
n = futures[future]
print(f"{n} is prime: {future.result()}")
Stable ABI (PEP 384)
PEP 384 defines a stable subset of the Python C API. Extensions compiled against this stable ABI no longer need to be recompiled for each new minor version of Python. This is a considerable advantage for binary package authors: a single compilation can work across Python 3.2, 3.3, 3.4, and beyond.
To use the stable ABI, extension authors must define Py_LIMITED_API at compile time and restrict themselves to functions documented as stable. The resulting files use the .abi3.so extension (or .pyd on Windows) instead of the usual version-specific suffix.
functools.lru_cache
The functools.lru_cache decorator caches function results in memory using an LRU (Least Recently Used) strategy. It is particularly effective for expensive functions called repeatedly with the same arguments.
from functools import lru_cache
import time
# Example 1: recursive computation with cache (Fibonacci sequence)
@lru_cache(maxsize=128)
def fibonacci(n):
"""Compute the n-th Fibonacci number."""
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# Without caching, fibonacci(100) would take astronomical time
print(fibonacci(100)) # 354224848179261915075
print(fibonacci.cache_info())
# CacheInfo(hits=98, misses=101, maxsize=128, currsize=101)
# Example 2: caching conversion results
@lru_cache(maxsize=256)
def convert_temperature(celsius):
"""Convert Celsius to Fahrenheit with caching."""
# Simulates an expensive computation or API call
return celsius * 9.0 / 5.0 + 32
# Repeated calls are instant
temperature_readings = [20, 22, 20, 18, 22, 20, 25, 18]
for temp in temperature_readings:
print(f"{temp} C = {convert_temperature(temp)} F")
print(convert_temperature.cache_info())
# hits=4 because 20, 22, and 18 are called multiple times
# Clear the cache if needed
convert_temperature.cache_clear()
Minor Improvements
.pycfiles are now stored in a__pycache__directory with a name that includes the Python version (PEP 3147).- The
loggingmodule gains dictionary-based configuration vialogging.config.dictConfig(). - The
sslmodule supports SSL contexts and certificate verification. - The
htmlmodule is added withhtml.escape(). - The
str.format_map()string formatting method is added.
Deprecations and Removals
Notable changes in this category:
- The
optparsemodule is deprecated in favor ofargparse. - Old insecure hash functions are deprecated in the
hashlibmodule. - Hash randomization is introduced (disabled by default, enabled by default starting with Python 3.3).
platform.dist()is marked as obsolete.
