Stable Release in branch 3.7
3.7.17
Released 05 Jun 2023
(3 years ago)
SoftwarePython
Version3.7
Status
End of life
Initial release3.7.0
27 Jun 2018
(8 years ago)
Latest release3.7.17
05 Jun 2023
(3 years ago)
End of life27 Jun 2023
(Ended 3 years ago)
Source codehttps://github.com/python/cpython/tree/v3.7.17
Documentationhttps://docs.python.org/release/3.7.17/
Downloadhttps://www.python.org/downloads/release/python-3717/
Python 3.7 ReleasesView full list

What Is New in Python 3.7

Python 3.7 was released on June 27, 2018. The defining additions are the dataclasses module, contextvars for async context propagation, breakpoint() as a standardized debugger entry point, postponed annotation evaluation, and nanosecond-precision time functions. CPython's startup time also improved significantly.

Category Change PEP / Reference
New Syntax Postponed evaluation of type annotations via from __future__ import annotations PEP 563
New Modules dataclasses -- auto-generated __init__, __repr__, __eq__ for classes PEP 557
New Modules contextvars -- context-local state for coroutines and threads PEP 567
New Modules importlib.resources -- access package data files without __file__ hacks --
New Built-ins breakpoint() -- configurable debugger entry point PEP 553
Language async and await become reserved keywords --
Language Dict insertion order is now a guaranteed language spec (not just CPython impl detail) --
Performance Nanosecond-resolution time functions (time.time_ns(), etc.) PEP 564
Performance Faster startup time -- attribute lookup improvements --
Interpreter Hash-based .pyc files for reproducible builds PEP 552
Interpreter UTF-8 mode (-X utf8) and legacy C locale coercion PEP 538, PEP 540
Interpreter Development mode (-X dev) with extra runtime checks --
asyncio Major overhaul -- new high-level API, running coroutines is now asyncio.run() --

What Are the Key New Features in Python 3.7?

dataclasses -- Boilerplate-Free Classes (PEP 557)

The @dataclass decorator auto-generates __init__, __repr__, __eq__, and optionally __lt__, __hash__, and __post_init__ based on class-level type annotations. This is the single most adopted stdlib addition of Python 3.7.

from dataclasses import dataclass, field

@dataclass(order=True)
class Point:
    x: float
    y: float
    label: str = field(default="origin", compare=False)

p1 = Point(1.0, 2.0)
p2 = Point(1.0, 2.0, label="home")
print(p1 == p2)  # True -- label excluded from comparison
print(repr(p1))  # Point(x=1.0, y=2.0, label='origin')

You control which fields participate in comparison, hashing, and repr independently. For mutable default values, use field(default_factory=list) -- not a bare [].

contextvars -- Context-Local State (PEP 567)

Context variables are the async-safe replacement for thread-local storage. Each coroutine runs in its own context copy, so setting a ContextVar inside a coroutine doesn't bleed into sibling coroutines sharing the same thread.

from contextvars import ContextVar

request_id: ContextVar[str] = ContextVar("request_id", default="none")

async def handle_request(rid: str):
    token = request_id.set(rid)
    await do_work()  # request_id is "rid" here, not visible to other coroutines
    request_id.reset(token)

async def do_work():
    print(request_id.get())  # prints the request-specific value

breakpoint() -- Pluggable Debugger (PEP 553)

Instead of importing pdb and calling pdb.set_trace(), you now just call breakpoint(). The actual debugger is configurable via the PYTHONBREAKPOINT environment variable -- set it to a dotted import path, or to 0 to disable all breakpoints without touching code.

# In code
breakpoint()  # drops into pdb by default

# To use a different debugger:
# PYTHONBREAKPOINT=pudb.set_trace

# To silence all breakpoints:
# PYTHONBREAKPOINT=0

How Did asyncio Change in Python 3.7?

Python 3.7 is where asyncio became genuinely pleasant to use. The biggest change: asyncio.run(coro) -- a single call to run a top-level coroutine, create an event loop, and clean it up automatically. Previously this required four or five lines of boilerplate.

import asyncio

async def main():
    print("hello")
    await asyncio.sleep(1)
    print("world")

asyncio.run(main())  # Python 3.7+

Other asyncio additions: asyncio.create_task() replaces the verbose loop.create_task(), asyncio.get_running_loop() raises RuntimeError if no loop is active (safer than get_event_loop()), and asyncio.current_task() / asyncio.all_tasks() for task introspection.

Postponed Annotation Evaluation (PEP 563)

With from __future__ import annotations, all annotations are stored as strings (lazily) rather than evaluated at definition time. This solves forward reference problems and reduces import-time overhead for annotation-heavy code.

from __future__ import annotations

class Node:
    def next(self) -> Node:  # Forward reference -- works without quotes
        ...

    def clone(self) -> Node:
        ...

Without the import, Node would not yet be defined at class body evaluation time. Postponed evaluation was planned to become the default in 3.10, but that change was deferred indefinitely due to compatibility concerns with runtime annotation consumers.

Performance Improvements and CPython Changes

  • Startup time improved -- method resolution and attribute lookup are faster, particularly for classes with many inherited attributes.
  • Six new nanosecond-precision time functions: time.time_ns(), time.perf_counter_ns(), time.monotonic_ns(), etc. These avoid floating-point precision loss on high-resolution clocks.
  • Hash-based .pyc files (PEP 552) allow content-based validation instead of timestamp comparison, enabling reproducible bytecode in build systems.
  • Dict ordering is now a language guarantee, not just a CPython implementation detail. Code can rely on insertion order without worrying about interpreter portability.
  • UTF-8 mode (-X utf8 or PYTHONUTF8=1) forces UTF-8 as the default encoding regardless of locale settings -- useful in containers and CI pipelines.

FAQ

Should I use dataclasses or attrs or plain classes in 2024?
dataclasses covers 80% of the use cases with zero dependencies. attrs is more powerful and older, with features like validators, converters, and slots support (though dataclasses also gained __slots__ support in 3.10). Choose dataclasses as the default; switch to attrs when you need validators or the performance of slots in older Python versions.

What is the difference between ContextVar and threading.local?
threading.local is per-thread. ContextVar is per-context -- and each coroutine automatically runs in its own child context. This means two coroutines on the same OS thread cannot see each other's ContextVar values unless they share a context explicitly. For async code, ContextVar is the correct tool.

Is the dict ordering guarantee retroactively true for Python 3.6?
In CPython 3.6, dict ordering was an implementation detail, not a spec guarantee. The guarantee was formalized in 3.7. Other Python implementations (PyPy, MicroPython) were not required to maintain insertion order before 3.7. In practice, if you need to support CPython only, 3.6 behaves the same, but portable code should target 3.7.

Does from __future__ import annotations affect runtime behavior?
Yes -- accessing __annotations__ directly will give you strings instead of resolved types. Code that does runtime annotation inspection (like Pydantic v1, older FastAPI, or custom DI frameworks) may break unless it calls typing.get_type_hints() to resolve the strings. Pydantic v2 handles this correctly.

When should I use asyncio.run() vs manually managing the event loop?
Use asyncio.run() for top-level entry points. It creates a fresh loop, runs the coroutine to completion, and cleans up. Only manage loops manually when embedding Python in a C extension or integrating with a foreign event loop (like a GUI toolkit's event loop). asyncio.run() should not be called from inside an already-running loop -- use await or asyncio.create_task() instead.

Releases In Branch 3.7

VersionRelease date
3.7.1705 Jun 2023
(3 years ago)
3.7.1606 Dec 2022
(3 years ago)
3.7.1510 Oct 2022
(3 years ago)
3.7.1406 Sep 2022
(3 years ago)
3.7.1316 Mar 2022
(4 years ago)
3.7.1204 Sep 2021
(4 years ago)
3.7.1128 Jun 2021
(5 years ago)
3.7.1016 Feb 2021
(5 years ago)
3.7.915 Aug 2020
(5 years ago)
3.7.827 Jun 2020
(6 years ago)
3.7.8rc117 Jun 2020
(6 years ago)
3.7.710 Mar 2020
(6 years ago)
3.7.7rc104 Mar 2020
(6 years ago)
3.7.618 Dec 2019
(6 years ago)
3.7.6rc111 Dec 2019
(6 years ago)
3.7.514 Oct 2019
(6 years ago)
3.7.5rc101 Oct 2019
(6 years ago)
3.7.408 Jul 2019
(7 years ago)
3.7.4rc202 Jul 2019
(7 years ago)
3.7.4rc118 Jun 2019
(7 years ago)
3.7.325 Mar 2019
(7 years ago)
3.7.3rc112 Mar 2019
(7 years ago)
3.7.223 Dec 2018
(7 years ago)
3.7.2rc111 Dec 2018
(7 years ago)
3.7.120 Oct 2018
(7 years ago)
3.7.1rc213 Oct 2018
(7 years ago)
3.7.1rc126 Sep 2018
(7 years ago)
3.7.027 Jun 2018
(8 years ago)
3.7.0rc112 Jun 2018
(8 years ago)
3.7.0b530 May 2018
(8 years ago)
3.7.0b402 May 2018
(8 years ago)
3.7.0b329 Mar 2018
(8 years ago)
3.7.0b228 Feb 2018
(8 years ago)
3.7.0b130 Jan 2018
(8 years ago)
3.7.0a409 Jan 2018
(8 years ago)
3.7.0a305 Dec 2017
(8 years ago)
3.7.0a217 Oct 2017
(8 years ago)
3.7.0a119 Sep 2017
(8 years ago)