Python 3.11 Changes#
New language features#
Fine-grained error locations in tracebacks#
In Python 3.11, decorative annotations are added to the tracebacks.
The symbols
^
and~
are embedded within the traceback. They’re used to guide the attention to the part of the code that’s causing the error, instead of just the line.
def inverse(number):
return 1 / number
print(inverse(0))
Error output in Python 3.10:
Traceback (most recent call last):
File "/Users/surya.kumar/workspace/file.py", line 4, in <module>
print(inverse(0))
File "/Users/surya.kumar/workspace/file.py", line 2, in inverse
return 1 / number
ZeroDivisionError: division by zero
Error output in Python 3.11 (use of symbols ^
and ~
):
Traceback (most recent call last):
File "/Users/surya.kumar/workspace/file.py", line 4, in <module>
print(inverse(0))
^^^^^^^^^^
File "/Users/surya.kumar/workspace/file.py", line 2, in inverse
return 1 / number
~~^~~~~~~~
ZeroDivisionError: division by zero
Note:
This feature may result in a small increase in interpreter memory usage and disk usage for compiled Python files.
To avoid storing the extra information and deactivate printing the extra traceback information, use the
-X no_debug_ranges
command line option or thePYTHONNODEBUGRANGES
environment variable.See the Python 3.11 release notes for more information.
Exception groups#
Exception Groups enable a program to raise and handle multiple unrelated exceptions simultaneously. They’re like regular exceptions wrapping several other regular exceptions.
You create an exception group by giving it a description and listing the exceptions that it wraps:
eg = ExceptionGroup("eg", [TypeError("int"), ValueError(0)])
When an exception group is raised it displays a nice traceback that illustrates the grouping and nesting of errors:
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| ExceptionGroup: eg (2 sub-exceptions)
+-+---------------- 1 ----------------
| TypeError: int
+---------------- 2 ----------------
| ValueError: 0
+------------------------------------
The new
except*
syntax generalizesexcept
to match subgroups of exception groups to for working effectively with them.
try:
raise eg
except* ValueError as ve:
print(f"ValueError handled: {ve.exceptions}")
except* TypeError as te:
print(f"TypeError handled: {te.exceptions}")
# ValueError handled: (ValueError(0),)
# TypeError handled: (TypeError('int'),)
See Python 3.11: Exceptions for more information.
Exception notes#
The
add_note()
method is added toBaseException
. It can be used to enrich exceptions with context information that is not available at the time when the exception is raised.A note can be added to an exception, and existing notes can be viewed by inspecting the
.__notes__
attribute in the following way:
err = ValueError(0)
err.add_note("0 is not allowed")
err.add_note("Python 3.11")
print(err.__notes__)
# ['0 is not allowed', 'Python 3.11']
raise err
# ValueError: 0
# 0 is not allowed
# Python 3.11
New typing features#
See Python 3.11: New typing features for more information on the changes in this section.
Variadic generics with TypeVarTuple
#
Python 3.11 introduces a specialized type variable, TypeVarTuple
, enabling variadic generics.
Using type variable tuples, you can create type hints that specify generic data structures of arbitrary shape and type:
from typing import TypeVarTuple, Generic
TValues = TypeVarTuple("TValues")
class Record(Generic[*TValues]):
key: int
values: Tuple[*TValues]
def __init__(self, key: int, *args: *TValues):
self.key = key
self.values = args
def update(self, *args: *TValues):
self.values = args
record1 = Record(1001, "Hello", 12.3, 1234)
record1. update("new word", 123.2, 32343)
Like regular tuples, type variable tuples can be of arbitrary length:
record1.update("more", "words", -0.342, True, {"hi": "I am a dict"})
record1.update()
See Python 3.11: Variadic generics for more information.
Self
type#
The new
Self
annotation provides a simple and intuitive way to annotate methods that return an instance of their class.Self
can also be used to annotate method parameters or attributes of the same type as their enclosing class.In the below example, the annotation
-> Self
indicates that__enter__(self)
will return an instance of the current class.
from typing import Self
class MyLock:
def __enter__(self) -> Self:
self.lock()
return self
See PEP 673 for more details.
Required
and NotRequired
with TypedDict
#
Python 3.11 introduces two new type qualifiers,
typing.Required
andtyping.NotRequired
, which allow defining a single TypedDict with a mix of both required and potentially-missing keys.All the fields are still required by default.
class Movie(TypedDict):
title: str
year: NotRequired[int]
m1: Movie = {"title": "Black Panther", "year": 2018} # Type Check Passed
m2: Movie = {"title": "Star Wars"} # Type Check Passed (year is not required)
m3: Movie = {"year": 2022} # # Type Check Failed (missing required field title)
See PEP 655 for more details.
LiteralString
#
A new type is added to the
typing
module:LiteralString
is a special kind of string type that’s defined literally in your code. I.eLiteralString
only accepts string values that are known to be made of literals. (A string literal is where you specify the contents of a string in a program.)Type checkers that can enforce sensitive functions (with LiteralString type), such as those that execute SQL statements or shell commands, are called only with static arguments. This provides protection against injection attacks.
from typing import LiteralString
def execute_sql(query: LiteralString):
...
execute_sql("SELECT * FROM users") # Type check Pass
table = "users"
execute_sql(f"SELECT * FROM {table}") # Type check Pass
user_input = input()
execute_sql("SELECT * FROM " + user_input) # Type check Fail
In the last example, even though the value of
user_input
happens to be the same as the value oftable
from earlier, the type checker will raise an error here.Users control the value of
user_input
and can potentially change it to something that’s unsafe for your application.See PEP 675 for more details.
Data class transforms#
Python 3.11 introduces a new decorator function in the
typing
module nameddataclass_transform
.This decorator can be applied to either a function that is itself a decorator, a class, or a metaclass.
The presence of
@dataclass_transform()
tells a static type checker that the decorated object performs runtime “magic” that transforms a class, giving itdataclass
-like behaviors.
import typing
@typing.dataclass_transform()
def create_model(cls: Type[T]) -> Type[T]:
cls.__init__ = ...
cls.__eq__ = ...
cls.__ne__ = ...
return cls
# The create_model decorator can now be used to create new model classes:
@create_model
class CustomerModel:
id: int
name: str
See PEP 681: Data class transforms for more details.
Other language changes#
Starred unpacking expressions in for
statements#
Starred unpacking expressions can now be used in for
statements.
This functionality was present, but not documented, in Python 3.9 and 3.10 stable releases.
See bpo-46725 for more details.
a = [1, 2, 3]
b = [11, 22, 33]
for x in *a, *b:
print(x, end=' ')
# 1, 2, 3, 11, 22, 33
Asynchronous comprehensions bug fix#
Asynchronous comprehensions are now allowed inside comprehensions in asynchronous functions. Outer comprehensions implicitly become asynchronous in this case. Introduced in bpo-33346 change.
Error handling for objects not supporting context managers#
A TypeError
is raised instead of an AttributeError
in with
statements and contextlib.ExitStack.enter_context()
for objects that don’t support the context manager protocol.
Similarly, in async with
statements and contextlib.AsyncExitStack.enter_async_context()
, a TypeError is raised for objects that don’t support the asynchronous context manager protocol.
See the Python 3.11 release notes for more details.
New method provides default implementation for __getstate__
#
A new object.__getstate__()
method has been added, providing a default implementation for __getstate__()
. Now copying and pickling instances of subclasses of certain built-in types (like bytearray
, set
, frozenset
, and others) now copies and pickles instance attributes implemented as slots.
This change has an unintended side effect: It trips up a small minority of existing Python projects not expecting object.__getstate__()
to exist. See the discussion for more details.
New command line option -P
and environment variable PYTHONSAFEPATH
#
A new -P
command line option and PYTHONSAFEPATH
environment variable have been added to disable the automatic prepending to sys.path
of the script’s directory when running a script, or the current directory when using -c
and -m
.
This change ensures that only standard library and installed modules are imported, preventing local (user-writable) directories from unintentionally or maliciously shadowing standard modules.
New string format specifier for signed zeros#
In Python 3.11, you can add a literal z
to the format string. This will force any zeros to be normalized to positive zero before formatting. (PEP 682 introduces a small extension to the format mini-language used by f-strings and str.format()
.)
small = -0.00311
f"A small number: {small:z.2f}"
# Python 3.11
# 'A small number: 0.00'
# Python 3.10
# ValueError: Invalid format specifier
See PEP 682 for more details.
Bytes no longer accepted on sys.path
#
Bytes are no longer accepted on sys.path
; see the Python 3.11 release notes for more information.
Optimizations#
String formatting#
The compiler now optimizes simple printf-style % formatting on string literals containing only the format codes %s
, %r
and %a
and makes it as fast as a corresponding f-string expression.
python -m timeit -s 'x = "%s has been building autonomous AI agents" % "mystring"'
Difference in M3 Pro, 11 core
Python 3.10 -> 6.51 nsec per loop
Python 3.11 -> 4.4 nsec per loop
Integer division#
Integer division (//)
is better tuned for optimization by compilers. It is now around 20% faster on x86-64 when dividing an int by a value smaller than 2**30
.
sum
function#
sum
is now nearly 30% faster for integers smaller than 2**30
.
Difference in M3 Pro, 11 core:
Python 3.10: 6.51 nsec per loop
Python 3.11: 4.13 nsec per loop
List resizing#
Resizing lists is streamlined for the common case, speeding up list.append()
by ≈15% and simple list comprehensions by up to 20-30%.
Dictionary hashing#
Dictionaries no longer store hash values when all keys are Unicode objects, decreasing dict
size.
For example, sys.getsizeof(dict.fromkeys("abcdefg"))
is reduced from 352 bytes to 272 bytes (23% smaller) on 64-bit platforms.
Large file transfers with asyncio.DatagramProtocol
#
Using asyncio.DatagramProtocol
is now orders of magnitude faster when transferring large files over UDP, with speeds over 100 times higher for a ≈60 MiB file. Find out more at gh-91487.
math.comb
and math.perm
with large arguments#
math
functions comb()
and perm
are now ≈10 times faster for large arguments (with a larger speedup for larger k). Find out more at bpo-37295.
statistics.mean
, statistics.variance
, and statistics.stdev
#
The statistics
functions mean
, variance
and stdev
now consume iterators in one pass rather than converting them to a list
first. This is twice as fast and can save substantial memory.
Faster unicode normalization of ASCII strings#
unicodedata.normalize()
now normalizes pure-ASCII strings in constant time. Check more at bpo-44987.
Improved modules#
datetime
#
datetime.UTC
is now added in Python 3.11, a convenience alias for datetime.timezone.utc
.
In Python 3.11, the following functions have been enhanced to parse almost all ISO 8601 formats:
datetime.date.fromisoformat
datetime.time.fromisoformat
datetime.datetime.fromisoformat
The only exceptions are those formats that include fractional hours and minutes.
inspect
#
getmembers_static()
is added. It returns all the members of an object in a list of (name, value)
pairs sorted by name without triggering dynamic lookup via the descriptor protocol, __getattr__
or __getattribute__
. Optionally, only return members that satisfy a given predicate.
See Python bug 30533 for more details.
math
#
Added
math.exp2(x)
: return 2 raised to the power of x.Added
math.cbrt(x)
: return the cube root of x.The behaviour of two
math.pow()
corner cases was changed, for consistency.The operations
math.pow(0.0, -math.inf)
andmath.pow(-0.0, -math.inf)
now returninf
.Previously they raised
ValueError
.
The
math.nan
value is now always available. (Prior to 3.11, In some implementations or platforms, this value might have been unavailable due to platform-specific constraints or variations in the underlying C library.)
pathlib
#
glob()
andrglob()
return only directories if pattern ends with a pathname components separator:sep
oraltsep
.
from pathlib import Path
list_of_all = [x for x in Path('.').glob('*/')]
# Python 3.10 -> list_of_all contains all directories & files
# Python 3.11 -> list_of_all contains only directories (as glob pattern is '*/')
traceback
#
traceback.StackSummary.format_frame_summary()
is added to allow users to override which frames appear in the traceback, and how they are formatted.traceback.TracebackException.print()
is added which prints the formattedTracebackException
instance to a file.
typing
#
typing.reveal_type()
is added. This is useful for asking a type checker what type it has inferred for a given expression. At runtime it prints the type of the received value.from typing import reveal_type a = 15 b = 7.2 c = reveal_type(a) + b reveal_type(c) print(c)
Output in
python file.py
:Runtime type is 'int' Runtime type is 'float' 22.2
Output in
mypy file.py
:file.py:6: note: Revealed type is "builtins.int" file.py:7: note: Revealed type is "builtins.float"
Any
can now be used as a base class. This can be useful for avoiding type checker errors with classes that can duck type anywhere or are highly dynamic, such as mocks.This means that the following code returns
True
in 3.11, whereas in 3.10 it returnsFalse
from typing import Any isinstance(Any, type)
The representation of empty tuple types (
Tuple[()]
) is simplified. This affects introspection, e.g.get_args(Tuple[()])
now evaluates to()
instead of((),)
.
Deprecations#
Chaining of classmethod
descriptors#
Chaining classmethod
descriptors is now deprecated.
It can no longer be used to wrap other descriptors such as
property
.It is due to design flaw of the feature and number of downstream problems.
To “pass-through” a
classmethod
, consider using the__wrapped__
attributeCheck more at gh-89519
Invalid octal escape sequences#
Octal escapes in string and bytes literals with values larger than 0o377 (255 in decimal) now produce a DeprecationWarning
. In a future Python version, they will raise a SyntaxWarning
and eventually a SyntaxError
.
Delegation of int
to __trunc__
#
The delegation of int()
to __trunc__()
is now deprecated. Calling int(a)
when type(a)
implements __trunc__()
but not __int__()
or __index__()
now raises a DeprecationWarning
. Check bpo-44977 for more.
Deprecated modules#
The following modules are deprecated in Python 3.11, and slated for removal in Python 3.13:
[
spwd
](https://docs.python.org/3.11/library/spwd.html#module-spwd “spwd: The shadow password database (getspnam() and friends).sre_compile
,sre_constants
, andsre_parse
are deprecated.
Updated deprecation warnings in configparser
#
In configparser
, warnings have been updated for the following deprecated objects:
configparser.SafeConfigParser
configparser.ParsingError.filename
configparser.RawConfigParser.readfp
configparser.LegacyInterpolation
(emitsDeprecationWarning
; to be removed in Python 3.13. Useconfigparser.BasicInterpolation
orconfigparser.ExtendedInterpolation
instead.)
Older importlib.resources
functions#
The older set of importlib.resources
functions were deprecated in favor of the replacements added in Python 3.9.
locale.getdefaultlocale
function#
The locale.getdefaultlocale()
function is deprecated and will be removed in Python 3.15. Use locale.setlocale()
, locale.getpreferredencoding(False)
and locale.getlocale()
functions instead.
locale.resetlocale
#
The locale.resetlocale()
function is deprecated and will be removed in Python 3.13. Use locale.setlocale(locale.LC_ALL, "")
instead.
typing.Text
#
typing.Text
, which exists solely to provide compatibility support between Python 2 and Python 3 code, is now deprecated. It is encouraged to use str
instead.
Keyword argument syntax for constructing typing.TypedDict
#
The keyword argument syntax for constructing typing.TypedDict
types is now deprecated.
Test case return values#
The behavior of returning a value from a TestCase
and IsolatedAsyncioTestCase
test methods (other than the default None
value) is now deprecated.
unittest
functions#
Deprecated the following not-formally-documented
unittest
functions, scheduled for removal in Python 3.13:unittest.findTestCases
unittest.makeSuite
unittest.getTestCaseNames
See the Python 3.11 release notes for alternatives.
unittest.TestProgram.usageExit
is deprecated, to be removed in 3.13.
re.template
, re.TEMPLATE
, and re.T
#
The re.template
function and the corresponding re.TEMPLATE
and re.T
flags are deprecated.
webbrowser.MacOSX
#
webbrowser.MacOSX
is deprecated and will be removed in Python 3.13.
Removals#
@asyncio.coroutine()
decorator deprecated since Python 3.8 is removed now; enabling legacy generator-based coroutines to be compatible withasync
/await
code. Useasync def
instead.Removed
asyncio.coroutines.CoroWrapper
used for wrapping legacy generator-based coroutine objects in the debug mode.Due to significant security concerns, the
_reuse_address_
parameter ofasyncio.loop.create_datagram_endpoint()
, disabled in Python 3.9, is now entirely removed.Removed the deprecated
binhex
module. Also removed the related, similarly-deprecated thesebinascii
functions.Removed the deprecated
distutils
bdist_msi
command. Usebdist_wheel
(wheel packages) instead.Removed the deprecated
__getitem__()
methods ofxml.dom.pulldom.DOMEventStream
,wsgiref.util.FileWrapper
andfileinput.FileInput
,Removed the deprecated
gettext
functionslgettext()
,ldgettext()
,lngettext()
andldngettext()
. Also removed thebind_textdomain_codeset()
function, theNullTranslations.output_charset()
andNullTranslations.set_output_charset()
methods, and the_codeset_
parameter oftranslation()
andinstall()
, since they are only used for thel*gettext()
functions.The deprecated
getargspec()
,formatargspec()
function andSignature.from_builtin()
andSignature.from_function()
methods from inspect are removed. Use these instead.Removed the
__class_getitem__()
method frompathlib.PurePath
Removed the
MailmanProxy
class in thesmtpd
module, as it is unusable without the externalmailman
package.Removed the deprecated
split()
method of_tkinter.TkappType
.Removed namespace package support from
unittest
discovery.Removed the undocumented private
float.__set_format__()
method (float.__setformat__()
previously).The
--experimental-isolated-subinterpreters
configure flag (and correspondingEXPERIMENTAL_ISOLATED_SUBINTERPRETERS
macro) have been removed.Pynche has been moved out and is being developed independently from the Python source tree.