# What’s new in Python 3.16

Editor:

  TBD

This article explains the new features in Python 3.16, compared to 3.15.

For full details, see the changelog.

Note

Prerelease users should be aware that this document is currently in draft form. It will be updated substantially as Python 3.16 moves towards release, so it’s worth checking back even after reading earlier versions.

## Summary — release highlights

## New features

## Other language changes

## New modules

- None yet.

## Improved modules

### gzip

- `gzip.open()` now accepts an optional argument `mtime` which is passed on to the constructor of the `GzipFile` class. (Contributed by Marin Misur in gh-91372.)

### lzma

- Add support of new BCJ filters ARM64 and RISC-V via `lzma.FILTER_ARM64` and `lzma.FILTER_RISCV`. Note that the new filters will work only if runtime library supports them. ARM64 filter requires `lzma` 5.4.0 or newer while RISC-V requires 5.6.0 or newer. (Contributed by Chien Wong in gh-115988.)

### logging

- `TimedRotatingFileHandler` now uses the creation time instead of the last modification time of an existing log file as the basis for the first rotation after handler creation, if supported by the OS and file system. This allows it to be used in short-running programs that start and end before the rotation interval expires. (Contributed by Iván Márton and Serhiy Storchaka in gh-84649.)

### math

- Added trigonometric functions that work in units of half turns, rather than radians. The new functions `math.acospi()`, `math.asinpi()`, `math.atanpi()`, and `math.atan2pi()` return half-turn angles. The new functions `math.cospi()`, `math.sinpi()`, and `math.tanpi()` take half-turn angle arguments. These functions are recommended by IEEE 754-2019 and standardized in C23. (Contributed by Jeff Epler in gh-150534.)

### os

- Add `os.pidfd_getfd()` for duplicating a file descriptor from another process via a pidfd. Available on Linux 5.6+. (Contributed by Maurycy Pawłowski-Wieroński in gh-149464.)

### shlex

- Add keyword-only parameter force to `shlex.quote()` to force quoting a string, even if it is already safe for a shell without being quoted. (Contributed by Jay Berry in gh-148846.)

### xml

- Add support for multiple multi-byte encodings in the `XML parser`: “cp932”, “cp949”, “cp950”, “Big5”,”EUC-JP”, “GB2312”, “GBK”, “johab”, and “Shift_JIS”. Add partial support (only BMP characters) for multi-byte encodings “Big5-HKSCS”, “EUC_JIS-2004”, “EUC_JISX0213”, “Shift_JIS-2004”, “Shift_JISX0213”, “utf-8-sig” and non-standard aliases like “UTF8” (without hyphen). The parser now raises `ValueError` for known unsupported multi-byte encodings such us “ISO-2022-JP” or “raw-unicode-escape” instead of failing later, when encounter non-ASCII data. (Contributed by Serhiy Storchaka in gh-62259.)

## Optimizations

### module_name

- TODO

## Removed

### annotationlib

- The `annotationlib.ForwardRef._evaluate()` method which has been deprecated since Python 3.14. Use `annotationlib.ForwardRef.evaluate()` or `typing.evaluate_forward_ref()` instead.

### array

- The `'u'` format code (`wchar_t`) which has been deprecated in documentation since Python 3.3 and at runtime since Python 3.13. Use `'w'` format code instead (`Py_UCS4`, always 4 bytes).

### asyncio

- The `asyncio.iscoroutinefunction()` which has been deprecated since Python 3.14. Use `inspect.iscoroutinefunction()` instead.

### functools

- Calling the Python implementation of `functools.reduce()` with function or sequence as keyword arguments has been deprecated since Python 3.14.

### logging

- Support for custom logging handlers with the strm argument is deprecated and scheduled for removal in Python 3.16. Define handlers with the stream argument instead.

### mimetypes

- Valid extensions start with a ‘.’ or are empty for `mimetypes.MimeTypes.add_type()`. Undotted extensions now raise a `ValueError`.

### shutil

- The `ExecError` exception which has been deprecated since Python 3.14. It has not been used by any function in `shutil` since Python 3.4. (Contributed by Stan Ulbrych in gh-149567.)

### symtable

- The `symtable.Class.get_methods()` method which has been deprecated since Python 3.14.

### sys

- The `_enablelegacywindowsfsencoding()` function which has been deprecated since Python 3.13. Use the `PYTHONLEGACYWINDOWSFSENCODING` environment variable instead. (Contributed by Stan Ulbrych in gh-149595.)

### sysconfig

- The `sysconfig.expand_makefile_vars()` function which has been deprecated since Python 3.14. Use the `vars` argument of `sysconfig.get_paths()` instead. (Contributed by Stan Ulbrych in gh-149499.)

### tarfile

- The undocumented and unused `tarfile.TarFile.tarfile` attribute has been deprecated since Python 3.13.

## Deprecated

- `abc`

  > - Soft-deprecated since Python 3.3 `abc.abstractclassmethod`, `abc.abstractstaticmethod`, and `abc.abstractproperty` now raise a `DeprecationWarning`. These classes will be removed in Python 3.21, instead use `abc.abstractmethod()` with `classmethod()`, `staticmethod()`, and `property` respectively.

- `ast`:

  - Classes `slice`, `Index`, `ExtSlice`, `Suite`, `Param`, `AugLoad` and `AugStore`, deprecated since Python 3.9, are no longer imported by `from ast import *` and issue a deprecation warning on use. The classes are slated for removal in Python 3.21. These types are not generated by the parser or accepted by the code generator.

  - The `dims` property of `ast.Tuple` objects, deprecated since Python 3.9, now issues a deprecation warning on use. This property is slated for removal in 3.21. Use `ast.Tuple.elts` instead.

### Pending removal in Python 3.17

- `datetime`:

  - `strptime()` calls using a format string containing `%e` (day of month) without a year. This has been deprecated since Python 3.15. (Contributed by Stan Ulbrych in gh-70647.)

- `collections.abc`:

  - `collections.abc.ByteString` is scheduled for removal in Python 3.17.

    Use `isinstance(obj, collections.abc.Buffer)` to test if `obj` implements the buffer protocol at runtime. For use in type annotations, either use `Buffer` or a union that explicitly specifies the types your code supports (e.g., `bytes | bytearray | memoryview`).

    `ByteString` was originally intended to be an abstract class that would serve as a supertype of both `bytes` and `bytearray`. However, since the ABC never had any methods, knowing that an object was an instance of `ByteString` never actually told you anything useful about the object. Other common buffer types such as `memoryview` were also never understood as subtypes of `ByteString` (either at runtime or by static type checkers).

    See PEP 688 for more details. (Contributed by Shantanu Jain in gh-91896.)

- `encodings`:

  - Passing non-ascii encoding names to `encodings.normalize_encoding()` is deprecated and scheduled for removal in Python 3.17. (Contributed by Stan Ulbrych in gh-136702.)

- `webbrowser`:

  - `webbrowser.MacOSXOSAScript` is deprecated in favour of `webbrowser.MacOS`. (gh-137586)

- `typing`:

  - Before Python 3.14, old-style unions were implemented using the private class `typing._UnionGenericAlias`. This class is no longer needed for the implementation, but it has been retained for backward compatibility, with removal scheduled for Python 3.17. Users should use documented introspection helpers like `typing.get_origin()` and `typing.get_args()` instead of relying on private implementation details.

  - `typing.ByteString`, deprecated since Python 3.9, is scheduled for removal in Python 3.17.

    Use `isinstance(obj, collections.abc.Buffer)` to test if `obj` implements the buffer protocol at runtime. For use in type annotations, either use `Buffer` or a union that explicitly specifies the types your code supports (e.g., `bytes | bytearray | memoryview`).

    `ByteString` was originally intended to be an abstract class that would serve as a supertype of both `bytes` and `bytearray`. However, since the ABC never had any methods, knowing that an object was an instance of `ByteString` never actually told you anything useful about the object. Other common buffer types such as `memoryview` were also never understood as subtypes of `ByteString` (either at runtime or by static type checkers).

    See PEP 688 for more details. (Contributed by Shantanu Jain in gh-91896.)

### Pending removal in Python 3.18

- No longer accept a boolean value when a file descriptor is expected. (Contributed by Serhiy Storchaka in gh-82626.)

- `decimal`:

  - The non-standard and undocumented `Decimal` format specifier `'N'`, which is only supported in the `decimal` module’s C implementation, has been deprecated since Python 3.13. (Contributed by Serhiy Storchaka in gh-89902.)

- Deprecations defined by PEP 829:

  - `import` lines in `name.pth` files are silently ignored.

  (Contributed by Barry Warsaw in gh-148641.)

### Pending removal in Python 3.19

- `ctypes`:

  - Implicitly switching to the MSVC-compatible struct layout by setting `_pack_` but not `_layout_` on non-Windows platforms.

- `hashlib`:

  - In hash function constructors such as `new()` or the direct hash-named constructors such as `md5()` and `sha256()`, their optional initial data parameter could also be passed a keyword argument named `data=` or `string=` in various `hashlib` implementations.

    Support for the `string` keyword argument name is now deprecated and slated for removal in Python 3.19.

    Before Python 3.13, the `string` keyword parameter was not correctly supported depending on the backend implementation of hash functions. Prefer passing the initial data as a positional argument for maximum backwards compatibility.

- `http.cookies`:

  - `http.cookies.Morsel.js_output()` is deprecated and will be removed in Python 3.19.

  - `http.cookies.BaseCookie.js_output()` is deprecated and will be removed in Python 3.19.

- `imaplib`:

  - Altering `IMAP4.file` is now deprecated and slated for removal in Python 3.19. This property is now unused and changing its value does not automatically close the current file.

    Before Python 3.14, this property was used to implement the corresponding `read()` and `readline()` methods for `IMAP4` but this is no longer the case since then.

### Pending removal in Python 3.20

- Calling the `__new__()` method of `struct.Struct` without the format argument is deprecated and will be removed in Python 3.20. Calling `__init__()` method on initialized `Struct` objects is deprecated and will be removed in Python 3.20.

  (Contributed by Sergey B Kirpichev and Serhiy Storchaka in gh-143715.)

- The `__version__`, `version` and `VERSION` attributes have been deprecated in these standard library modules and will be removed in Python 3.20. Use `sys.version_info` instead.

  - `argparse`

  - `csv`

  - `ctypes`

  - `ctypes.macholib`

  - `decimal` (use `decimal.SPEC_VERSION` instead)

  - `http.server`

  - `imaplib`

  - `ipaddress`

  - `json`

  - `logging` (`__date__` also deprecated)

  - `optparse`

  - `pickle`

  - `platform`

  - `re`

  - `socketserver`

  - `tabnanny`

  - `tarfile`

  - `tkinter.font`

  - `tkinter.ttk`

  - `wsgiref.simple_server`

  - `xml.etree.ElementTree`

  - `xml.sax.expatreader`

  - `xml.sax.handler`

  - `zlib`

  (Contributed by Hugo van Kemenade and Stan Ulbrych in gh-76007.)

- Deprecations defined by PEP 829:

  - Warnings are produced for `import` lines found in `name.pth` files.

  - `name.pth` files are no longer decoded in the locale encoding by default. They MUST be encoded in `utf-8-sig`.

  (Contributed by Barry Warsaw in gh-148641.)

- `ast`:

  - Creating instances of abstract AST nodes (such as `ast.AST` or `ast.expr`) is deprecated and will raise an error in Python 3.20.

### Pending removal in Python 3.21

- `abc`

  > - Soft-deprecated since Python 3.3 `abc.abstractclassmethod`, `abc.abstractstaticmethod`, and `abc.abstractproperty` now raise a `DeprecationWarning`. These classes will be removed in Python 3.21, instead use `abc.abstractmethod()` with `classmethod()`, `staticmethod()`, and `property` respectively.

- `ast`:

  - Classes `slice`, `Index`, `ExtSlice`, `Suite`, `Param`, `AugLoad` and `AugStore`, will be removed in Python 3.21. These types are not generated by the parser or accepted by the code generator.

  - The `dims` property of `ast.Tuple` will be removed in Python 3.21. Use the `ast.Tuple.elts` property instead.

### Pending removal in future versions

The following APIs will be removed in the future, although there is currently no date scheduled for their removal.

- `argparse`:

  - Nesting argument groups and nesting mutually exclusive groups are deprecated.

  - Passing the undocumented keyword argument prefix_chars to `add_argument_group()` is now deprecated.

  - The `argparse.FileType` type converter is deprecated.

- `builtins`:

  - Generators: `throw(type, exc, tb)` and `athrow(type, exc, tb)` signature is deprecated: use `throw(exc)` and `athrow(exc)` instead, the single argument signature.

  - Currently Python accepts numeric literals immediately followed by keywords, for example `0in x`, `1or x`, `0if 1else 2`. It allows confusing and ambiguous expressions like `[0x1for x in y]` (which can be interpreted as `[0x1 for x in y]` or `[0x1f or x in y]`). A syntax warning is raised if the numeric literal is immediately followed by one of keywords `and`, `else`, `for`, `if`, `in`, `is` and `or`. In a future release it will be changed to a syntax error. (gh-87999)

  - Support for `__index__()` and `__int__()` method returning non-int type: these methods will be required to return an instance of a strict subclass of `int`.

  - Support for `__float__()` method returning a strict subclass of `float`: these methods will be required to return an instance of `float`.

  - Support for `__complex__()` method returning a strict subclass of `complex`: these methods will be required to return an instance of `complex`.

  - Passing a complex number as the real or imag argument in the `complex()` constructor is now deprecated; it should only be passed as a single positional argument. (Contributed by Serhiy Storchaka in gh-109218.)

- `calendar`: `calendar.January` and `calendar.February` constants are deprecated and replaced by `calendar.JANUARY` and `calendar.FEBRUARY`. (Contributed by Prince Roshan in gh-103636.)

- `codecs`: use `open()` instead of `codecs.open()`. (gh-133038)

- `codeobject.co_lnotab`: use the `codeobject.co_lines()` method instead.

- `datetime`:

  - `utcnow()`: use `datetime.datetime.now(tz=datetime.UTC)`.

  - `utcfromtimestamp()`: use `datetime.datetime.fromtimestamp(timestamp, tz=datetime.UTC)`.

- `gettext`: Plural value must be an integer.

- `importlib`:

  - `cache_from_source()` debug_override parameter is deprecated: use the optimization parameter instead.

- `importlib.metadata`:

  - `EntryPoints` tuple interface.

  - Implicit `None` on return values.

- `logging`: the `warn()` method has been deprecated since Python 3.3, use `warning()` instead.

- `mailbox`: Use of StringIO input and text mode is deprecated, use BytesIO and binary mode instead.

- `os`: Calling `os.register_at_fork()` in a multi-threaded process.

- `os.path`: `os.path.commonprefix()` is deprecated, use `os.path.commonpath()` for path prefixes. The `os.path.commonprefix()` function is being deprecated due to having a misleading name and module. The function is not safe to use for path prefixes despite being included in a module about path manipulation, meaning it is easy to accidentally introduce path traversal vulnerabilities into Python programs by using this function.

- `pydoc.ErrorDuringImport`: A tuple value for exc_info parameter is deprecated, use an exception instance.

- `re`: More strict rules are now applied for numerical group references and group names in regular expressions. Only sequence of ASCII digits is now accepted as a numerical reference. The group name in bytes patterns and replacement strings can now only contain ASCII letters and digits and underscore. (Contributed by Serhiy Storchaka in gh-91760.)

- `shutil`: `rmtree()`’s onerror parameter is deprecated in Python 3.12; use the onexc parameter instead.

- `ssl` options and protocols:

  - `ssl.SSLContext` without protocol argument is deprecated.

  - `ssl.SSLContext`: `set_npn_protocols()` and `selected_npn_protocol()` are deprecated: use ALPN instead.

  - `ssl.OP_NO_SSL*` options

  - `ssl.OP_NO_TLS*` options

  - `ssl.PROTOCOL_SSLv3`

  - `ssl.PROTOCOL_TLS`

  - `ssl.PROTOCOL_TLSv1`

  - `ssl.PROTOCOL_TLSv1_1`

  - `ssl.PROTOCOL_TLSv1_2`

  - `ssl.TLSVersion.SSLv3`

  - `ssl.TLSVersion.TLSv1`

  - `ssl.TLSVersion.TLSv1_1`

- `threading` methods:

  - `threading.Condition.notifyAll()`: use `notify_all()`.

  - `threading.Event.isSet()`: use `is_set()`.

  - `threading.Thread.isDaemon()`, `threading.Thread.setDaemon()`: use `threading.Thread.daemon` attribute.

  - `threading.Thread.getName()`, `threading.Thread.setName()`: use `threading.Thread.name` attribute.

  - `threading.currentThread()`: use `threading.current_thread()`.

  - `threading.activeCount()`: use `threading.active_count()`.

- `typing.Text` (gh-92332).

- The internal class `typing._UnionGenericAlias` is no longer used to implement `typing.Union`. To preserve compatibility with users using this private class, a compatibility shim will be provided until at least Python 3.17. (Contributed by Jelle Zijlstra in gh-105499.)

- `unittest.IsolatedAsyncioTestCase`: it is deprecated to return a value that is not `None` from a test case.

- `urllib.parse` deprecated functions: `urlparse()` instead

  - `splitattr()`

  - `splithost()`

  - `splitnport()`

  - `splitpasswd()`

  - `splitport()`

  - `splitquery()`

  - `splittag()`

  - `splittype()`

  - `splituser()`

  - `splitvalue()`

  - `to_bytes()`

- `wsgiref`: `SimpleHandler.stdout.write()` should not do partial writes.

- `xml.etree.ElementTree`: Testing the truth value of an `Element` is deprecated. In a future release it will always return `True`. Prefer explicit `len(elem)` or `elem is not None` tests instead.

- `sys._clear_type_cache()` is deprecated: use `sys._clear_internal_caches()` instead.

## Porting to Python 3.16

This section lists previously described changes and other bugfixes that may require changes to your code.

## Build changes

- Remove the bundled copy of the libmpdec decimal library from the CPython source tree to simplify maintenence and updates. The `decimal` module will now unconditionally use the system’s libmpdec decimal library. Also remove the now unused `--with-system-libmpdec` configure flag. This change has no impact on binary releases of Python, which have been built against a separate copy of libmpdec for the past several releases.

  (Contributed by Sergey B Kirpichev in gh-115119.)

- Add a `--with-build-details-suffix` configure flag to allow Linux distributions that co-install multiple versions of Python in the same tree to avoid `build-details.json` clashes.

  (Contributed by Stefano Rivera in gh-131372.)

## C API changes

### New features

- TODO

### Porting to Python 3.16

- TODO

### Deprecated C APIs

- `PyGen_New()`, `PyGen_NewWithQualName()`, `PyCoro_New()`, and `PyAsyncGen_New()` are deprecated. They are scheduled for removal in 3.18.

#### Pending removal in Python 3.18

- The following private functions are deprecated and planned for removal in Python 3.18:

  - `_PyBytes_Join()`: use `PyBytes_Join()`.

  - `_PyDict_GetItemStringWithError()`: use `PyDict_GetItemStringRef()`.

  - `_PyDict_Pop()`: use `PyDict_Pop()`.

  - `_PyLong_Sign()`: use `PyLong_GetSign()`.

  - `_PyLong_FromDigits()` and `_PyLong_New()`: use `PyLongWriter_Create()`.

  - `_PyThreadState_UncheckedGet()`: use `PyThreadState_GetUnchecked()`.

  - `_PyUnicode_AsString()`: use `PyUnicode_AsUTF8()`.

  - `_PyUnicodeWriter_Init()`: replace `_PyUnicodeWriter_Init(&writer)` with `writer = PyUnicodeWriter_Create(0)`.

  - `_PyUnicodeWriter_Finish()`: replace `_PyUnicodeWriter_Finish(&writer)` with `PyUnicodeWriter_Finish(writer)`.

  - `_PyUnicodeWriter_Dealloc()`: replace `_PyUnicodeWriter_Dealloc(&writer)` with `PyUnicodeWriter_Discard(writer)`.

  - `_PyUnicodeWriter_WriteChar()`: replace `_PyUnicodeWriter_WriteChar(&writer, ch)` with `PyUnicodeWriter_WriteChar(writer, ch)`.

  - `_PyUnicodeWriter_WriteStr()`: replace `_PyUnicodeWriter_WriteStr(&writer, str)` with `PyUnicodeWriter_WriteStr(writer, str)`.

  - `_PyUnicodeWriter_WriteSubstring()`: replace `_PyUnicodeWriter_WriteSubstring(&writer, str, start, end)` with `PyUnicodeWriter_WriteSubstring(writer, str, start, end)`.

  - `_PyUnicodeWriter_WriteASCIIString()`: replace `_PyUnicodeWriter_WriteASCIIString(&writer, str)` with `PyUnicodeWriter_WriteASCII(writer, str)`.

  - `_PyUnicodeWriter_WriteLatin1String()`: replace `_PyUnicodeWriter_WriteLatin1String(&writer, str)` with `PyUnicodeWriter_WriteUTF8(writer, str)`.

  - `_PyUnicodeWriter_Prepare()`: (no replacement).

  - `_PyUnicodeWriter_PrepareKind()`: (no replacement).

  - `_Py_HashPointer()`: use `Py_HashPointer()`.

  - `_Py_fopen_obj()`: use `Py_fopen()`.

  - `PyGen_New()`: (no replacement).

  - `PyGen_NewWithQualName()`: (no replacement).

  - `PyCoro_New()`: (no replacement).

  - `PyAsyncGen_New()`: (no replacement).

  The pythoncapi-compat project can be used to get these new public functions on Python 3.13 and older. (Contributed by Victor Stinner in gh-128863.)

#### Pending removal in Python 3.19

- PEP 456 embedders support for the string hashing scheme definition.

#### Pending removal in Python 3.20

- `_PyObject_CallMethodId()`, `_PyObject_GetAttrId()` and `_PyUnicode_FromId()` are deprecated since 3.15 and will be removed in 3.20. Instead, use `PyUnicode_InternFromString()` and cache the result in the module state, then call `PyObject_CallMethod()` or `PyObject_GetAttr()`. (Contributed by Victor Stinner in gh-141049.)

- The `cval` field in `PyComplexObject` (gh-128813). Use `PyComplex_AsCComplex()` and `PyComplex_FromCComplex()` to convert a Python complex number to/from the C `Py_complex` representation.

- Macros `Py_MATH_PIl` and `Py_MATH_El`.

#### Pending removal in future versions

The following APIs are deprecated and will be removed, although there is currently no date scheduled for their removal.

- `Py_TPFLAGS_HAVE_FINALIZE`: Unneeded since Python 3.8.

- `PyErr_Fetch()`: Use `PyErr_GetRaisedException()` instead.

- `PyErr_NormalizeException()`: Use `PyErr_GetRaisedException()` instead.

- `PyErr_Restore()`: Use `PyErr_SetRaisedException()` instead.

- `PyModule_GetFilename()`: Use `PyModule_GetFilenameObject()` instead.

- `PyOS_AfterFork()`: Use `PyOS_AfterFork_Child()` instead.

- `PySlice_GetIndicesEx()`: Use `PySlice_Unpack()` and `PySlice_AdjustIndices()` instead.

- `PyUnicode_READY()`: Unneeded since Python 3.12

- `PyErr_Display()`: Use `PyErr_DisplayException()` instead.

- `_PyErr_ChainExceptions()`: Use `_PyErr_ChainExceptions1()` instead.

- `PyBytesObject.ob_shash` member: call `PyObject_Hash()` instead.

- Thread Local Storage (TLS) API:

  - `PyThread_create_key()`: Use `PyThread_tss_alloc()` instead.

  - `PyThread_delete_key()`: Use `PyThread_tss_free()` instead.

  - `PyThread_set_key_value()`: Use `PyThread_tss_set()` instead.

  - `PyThread_get_key_value()`: Use `PyThread_tss_get()` instead.

  - `PyThread_delete_key_value()`: Use `PyThread_tss_delete()` instead.

  - `PyThread_ReInitTLS()`: Unneeded since Python 3.7.

### Removed C APIs