Thought leadership from the most innovative tech companies, all in one place.

Python 3.12: A Game-Changer in Performance and Efficiency

Exploring the Exciting New Additions, Updates, and Changes in Python 3.12

Python 3.12, the latest version of the Python programming language, is expected to bring major optimizations and improvements to the language, with a focus on enhancing the speed, performance, and stability of the interpreter. This new release is designed to make Python a more powerful and efficient tool for developers, particularly for large and complex applications.

Improved Multi-Threaded Parallelism

Python is taking steps towards improved multi-threaded parallelism by transitioning from a single global interpreter lock per process to a global interpreter lock per sub-interpreter. With PEP 684 and PEP 554, sub-interpreters can be created from Python, thus enabling genuine multi-threaded parallelism, that is a revolution!.

Expanded Specializations

The development team has evaluated which bytecodes would benefit the most from specialization and intends to finish the high-benefit ones remaining for Python 3.12

Compact Object Structs

The size of Python object structures will be reduced in version 3.12, improving overall memory usage and cache coherency. Some compromises between backward compatibility and performance will be necessary and will result in a PEP to reach a consensus.

Lower Memory Management

Overhead The size of objects will not only be reduced, but their layout will also become more uniform. This will offer opportunities to optimize memory allocation and freeing and hasten the process of object traversal during garbage collection and de-allocation.

Revamped Trace Optimizer

A major improvement in version 3.12 of Python is the Trace Optimizer. Unlike the previous version where the emphasis was on replacing single opcodes with faster, context-specific ones, the focus has now shifted towards optimizing sequences of multiple opcodes. To achieve this, many of the high-level opcodes will be swapped with lower-level opcodes that provide greater optimization possibilities. Furthermore, these simplified opcodes will bring the interpreter closer to a set of instructions that can be transformed into machine code, both in CPython and in JIT projects from third-party developers.

Declarative Interpreter Loop Generation

The interpreter loop will be generated from a declarative description, which will decrease the chance of bugs caused by the interpreter loop being out of sync with other functions. Additionally, this change will make it possible to experiment with significant changes to the interpreter loop.

Stabilized API

To further enhance the quality of the CPython codebase, the development team is taking the following actions:

Simplifying Maintenance and Testing of the Compiler:

The team is working towards reducing the dependence between the different stages of compilation, making it easier to maintain and test the compiler.

Enhancing Code Coverage:

The CPython test suite at the C level will be monitored and improved to increase code coverage. Expanding the Pyperformance Suite: The pyperformance benchmarking suite will be improved to include more realistic, real-world workloads.

Assisting with Performance-Related Issues:

The team will provide support for CPython issues and PRs, particularly those related to performance.

Broadening the Standard Benchmarking Results:

The set of standard benchmarking machines and results will be expanded to include macOS and Windows.

Collaborating with Major Python Users:

The development team will work with major projects that use Python internals to help them accommodate changes in the CPython interpreter.

Removed and Deprecated Features

With the release of Python 3.12, distutils has finally been removed. According to PEP 632, distutils was marked as deprecated in Python 3.10 and will no longer be a part of the standard library in Python 3.12. Importing from distutils will result in an error, as there will be no backwards compatibility offered.

Distutils was once the preferred module for package management in Python, but its limitations led to the rise of setuptools, which has now become the recommended solution according to the Python Packaging User Guide. Setuptools still uses some functionality from distutils, but it has integrated a copy of the latter and is no longer dependent on the standard library. Pip has also been replacing distutils with setuptools for some time now, so it makes sense to remove the legacy distutils module in Python 3.12.

In addition, Python 3.12 will also remove the wstr and wstr_length members from Unicode, as indicated in PEP 623. This change is in line with the deprecation of certain Unicode APIs in PEP 393. The removal of these members has resulted in a reduction of object size by 8 or 16 bytes on 64-bit platforms.

Improved Error Reporting in Python 3.12

The latest release of Python, version 3.12, will go for improved error messages, specifically for NameError raised in the top-level for modules in the standard library. The interpreter will also now provide suggestions in the error message.

class A:
def **init**(self):
self.blech = 1

def foo(self):
somethin = blech

> > > A().foo()
> > > File "<stdin>", line 1

    somethin = blech

NameError: name 'blech' is not defined. Did you mean: 'self.blech'?

Deprecation of Unittest Features in Python 3.12

As part of the release of Python 3.12, a number of features from the unittest module that were previously deprecated in earlier versions (mainly v3.1 and 3.2) will now be removed. The removals will include:

  • Many TestCase method aliases, such as failUnless, failIf, failUnlessEqual, failIfEqual, failUnlessAlmostEqual, failIfAlmostEqual, failUnlessRaises, assert_, assertEquals, assertNotEquals, assertAlmostEquals, assertNotAlmostEquals, assertRegexpMatches, assertRaisesRegexp, and assertNotRegexpMatches

  • The TestCase method assertDictContainsSubset

  • The use_load_tests parameter in TestLoader.loadTestsFromModule

  • The TextTestResult alias of TextTestResult

Changes in the Python API

  • 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.)

  • Removed randrange()functionality deprecated since Python 3.10. Formerly, randrange(10.0) losslessly converted to randrange(10). Now, it raises a [TypeError]( "TypeError"). Also, the exception raised for non-integral values such as randrange(10.5) or randrange('10') has been changed from [ValueError]( "ValueError") to [TypeError]( "TypeError"). This also prevents bugs where randrange(1e25) would silently select from a larger range than randrange(1025). (Originally suggested by Serhiy Storchaka gh-86388.)

  • [argparse.ArgumentParser]( "argparse.ArgumentParser") changed encoding and error handler for reading arguments from file (e.g. fromfile_prefix_chars option) from default text encoding (e.g. [locale.getpreferredencoding(False)]( "locale.getpreferredencoding")) to filesystem encoding and error handler. Argument files should be encoded in UTF-8 instead of ANSI Codepage on Windows.

  • Removed the asyncore-based smtpd module deprecated in Python 3.4.7 and 3.5.4. A recommended replacement is the [asyncio]( "asyncio: Asynchronous I/O.")-based aiosmtpd PyPI module.

  • shlex.split(): Passing None for s argument now raises an exception, rather than reading [sys.stdin]( "sys.stdin"). The feature was deprecated in Python 3.9. (Contributed by Victor Stinner in gh-94352.)

  • The [os]( "os: Miscellaneous operating system interfaces.") module no longer accepts bytes-like paths, like [bytearray]( "bytearray") and [memoryview]( "memoryview") types: only the exact [bytes]( "bytes") type is accepted for bytes strings. (Contributed by Victor Stinner in gh-98393.)

  • [syslog.openlog()]( "syslog.openlog") and [syslog.closelog()]( "syslog.closelog") now fail if used in subinterpreters. [syslog.syslog()]( "syslog.syslog") may still be used in subinterpreters, but now only if [syslog.openlog()]( "syslog.openlog") has already been called in the main interpreter. These new restrictions do not apply to the main interpreter, so only a very small set of users might be affected. This change helps with interpreter isolation. Furthermore, [syslog]( "syslog: An interface to the Unix syslog library routines. (Unix)") is a wrapper around process-global resources, which are best managed from the main interpreter. (Contributed by Dong-hee Na in gh-99127.)

Other Enhancements and Additions to the Language

Although it's not possible to share every modification in Python 3.12, here is a brief overview of some of the additional improvements and changes:

  • The introduction of os.path.isjunction() in the standard library os module, allowing users to check if a path is a junction
  • A new pathlib.Path.walk() method for walking directory trees, similar to os.walk()
  • Removal of several modules and APIs previously deprecated in previous Python versions

For a complete list of all the changes planned for the release of Python 3.12, refer to the official documentation.


The Python 3.12 release includes several improvements and changes to the language. The distutils module has been marked as deprecated and will be removed in the release of Python 3.12. Instead, the recommended module for package management is setuptools. In addition, the wstr and wstr_length members will be removed from Unicode.

Error messages will also be improved, particularly with NameErrors in the top-level for standard library modules. The unittest module will have several deprecated features removed, including method aliases and parameters.

Other changes include the introduction of the os.path.isjunction() member to check for junction paths and the pathlib.Path.walk() method for walking directory trees. Several modules and APIs previously deprecated in earlier versions will also be removed.

Continue Learning