Latest in branch 3.3
3.3.7
Released 19 Sep 2017
(8 years ago)
SoftwarePython
Version3.3
Status
End of life
Initial release3.3.0
29 Sep 2012
(13 years ago)
Latest release3.3.7
19 Sep 2017
(8 years ago)
End of life29 Sep 2017
(Ended 8 years, 8 months ago)
Source codehttps://github.com/python/cpython/tree/v3.3.7
Documentationhttps://docs.python.org/release/3.3.7/
Downloadhttps://www.python.org/downloads/release/python-337/
Python 3.3 ReleasesView full list

What Is New in Python 3.3

Python 3.3 was released on September 29, 2012. The headline additions are the yield from syntax for delegating sub-generators (the foundation of what later became await), the Virtual Environments module venv, and a redesigned import system via importlib. Python 3.3 also introduced a more flexible string representation for Unicode strings, cutting memory usage significantly for ASCII-heavy workloads.

Category Change PEP / Reference
New Syntax yield from -- sub-generator delegation PEP 380
New Syntax raise X from Y -- explicit exception chaining PEP 3134
New Modules venv -- lightweight virtual environments PEP 405
New Modules ipaddress -- IPv4/IPv6 address manipulation PEP 3144
New Modules lzma -- LZMA/XZ compression --
New Modules faulthandler -- debug-mode crash dumps from Python PEP 423
Interpreter Flexible string representation (PEP 393) -- Latin-1, UCS-2, or UCS-4 per string PEP 393
Interpreter Redesigned import system -- fully implemented in Python via importlib PEP 302, PEP 328
Interpreter Namespace packages -- packages without __init__.py PEP 420
Security Hash randomization enabled by default (PYTHONHASHSEED) --
Performance Unicode string memory footprint reduced by up to 3-4x for ASCII text PEP 393

yield from -- Sub-Generator Delegation (PEP 380)

The yield from expression lets a generator delegate to a sub-generator transparently. Values from the inner generator flow out through the outer one, send() calls flow in, and the return value of the inner generator becomes the value of the yield from expression. This was the direct predecessor of await in Python 3.5.

def inner():
    yield 1
    yield 2
    return "inner done"

def outer():
    result = yield from inner()  # delegates to inner()
    print(f"inner returned: {result}")
    yield 3

list(outer())  # [1, 2, 3]; prints "inner returned: inner done"

Before yield from, delegating to a sub-generator required a manual for item in sub_gen: yield item loop -- which lost the ability to pass send() values and return values back to the caller.

venv -- Built-in Virtual Environments (PEP 405)

Python 3.3 ships venv as a standard module, replacing the third-party virtualenv for most use cases. A virtual environment is a lightweight, isolated Python installation with its own site-packages directory.

# Create a virtual environment
python3 -m venv .venv

# Activate (Linux/macOS)
source .venv/bin/activate

# Activate (Windows)
.venv\Scripts\activate.bat

# Install packages into the environment
pip install requests

The key difference from virtualenv: venv does not copy the full Python binary -- it uses symlinks (or shims on Windows), making environments smaller and faster to create.

Flexible String Representation (PEP 393)

Before Python 3.3, every Unicode string used UCS-2 or UCS-4 format regardless of content, meaning a string of 100 ASCII characters occupied 200 or 400 bytes. PEP 393 changed this so CPython uses the narrowest representation that fits the actual characters: Latin-1 for strings with codepoints up to U+00FF, UCS-2 up to U+FFFF, and UCS-4 only when needed. For typical English text, this cuts string memory by 3-4x and speeds up ASCII string operations.

Other Notable Additions in Python 3.3

  • Namespace packages (PEP 420): A directory without an __init__.py file is now recognized as a "namespace package," allowing packages to be split across multiple directories or distribution packages.
  • ipaddress module (PEP 3144): ipaddress.IPv4Address, IPv6Address, IPv4Network, IPv6Network -- clean objects for network programming without string parsing.
  • faulthandler: Dumps a Python traceback on segfault or SIGFPE, which was previously impossible from within Python. Enable with python -X faulthandler or faulthandler.enable().
  • Explicit exception chaining (PEP 3134): raise NewError from original_error sets the __cause__ attribute, and Python prints both exceptions and their chain when a traceback is displayed.
  • lzma module: Python gains native LZMA/XZ compression -- the same format used for .tar.xz archives. Higher compression ratio than gzip or bzip2 at the cost of slower compression speed.

FAQ

What is the connection between yield from in 3.3 and await in 3.5?
await is semantically built on the same mechanism as yield from. Internally, the asyncio event loop uses generators and yield from delegation. The async def/await keywords in 3.5 are a cleaner syntax over the same machinery, with added restrictions (can only be used in async-designated functions) that make the intent unambiguous.

Is venv the same as virtualenv?
Similar, but not identical. venv is the stdlib version and creates lighter environments using symlinks. virtualenv (third-party) supports older Python versions, offers more configuration options, and creates environments faster via wheel caching. For modern Python (3.3+), venv is sufficient for most workflows. Use virtualenv when you need features like --copies or compatibility with older Pythons.

Do namespace packages require any changes to existing code?
No, existing packages with __init__.py continue to work unchanged. Namespace packages are an additive feature -- directories without __init__.py that would previously have been ignored are now treated as namespace packages. This only matters when you intentionally want to split a logical package across multiple filesystem locations or distributions.

Is hash randomization in Python 3.3 enabled by default?
Yes, starting with 3.3. The hash values of str, bytes, and datetime objects are randomized per-process by default (seeded from os.urandom()). This prevents hash collision denial-of-service attacks. Set PYTHONHASHSEED=0 to disable and get deterministic hashes, or a specific integer seed for reproducible results in testing.

Can raise X from None suppress the original exception context?
Yes. raise NewError("msg") from None sets __cause__ to None and __suppress_context__ to True, which suppresses the "During handling of the above exception, another exception occurred:" message. This is the right pattern when you're intentionally converting one exception type to another and don't want to expose the original.

Releases In Branch 3.3

VersionRelease date
3.3.719 Sep 2017
(8 years ago)
3.3.7rc106 Sep 2017
(8 years ago)
3.3.612 Oct 2014
(11 years ago)
3.3.6rc104 Oct 2014
(11 years ago)
3.3.509 Mar 2014
(12 years ago)
3.3.5rc202 Mar 2014
(12 years ago)
3.3.5rc123 Feb 2014
(12 years ago)
3.3.409 Feb 2014
(12 years ago)
3.3.4rc127 Jan 2014
(12 years ago)
3.3.317 Nov 2013
(12 years ago)
3.3.3rc211 Nov 2013
(12 years ago)
3.3.3rc127 Oct 2013
(12 years ago)
3.3.212 May 2013
(13 years ago)
3.3.106 Apr 2013
(13 years ago)
3.3.1rc125 Mar 2013
(13 years ago)
3.3.029 Sep 2012
(13 years ago)
3.3.0rc323 Sep 2012
(13 years ago)
3.3.0rc208 Sep 2012
(13 years ago)
3.3.0rc125 Aug 2012
(13 years ago)
3.3.0b211 Aug 2012
(13 years ago)
3.3.0b126 Jun 2012
(13 years ago)
3.3.0a430 May 2012
(14 years ago)
3.3.0a301 May 2012
(14 years ago)
3.3.0a201 Apr 2012
(14 years ago)
3.3.0a104 Mar 2012
(14 years ago)