What’s new in Python 3.8?#

In Python 3.8, the syntax is simplified and support for C libraries is also improved. Below is a brief overview of some of the new features. You can get a complete overview in What’s New In Python 3.8.

Installation#

Check#

[1]:
!python3 -V
Python 3.8.0

or

[ ]:
import sys
assert sys.version_info[:2] >= (3, 8)

Assignment Expressions: Walrus operator :=#

So far, e.g. env_base can be determined by pip as follows:

[ ]:
import os
[ ]:
def _getuserbase():
    env_base = os.environ.get("PYTHONUSERBASE", None)
    if env_base:
        return env_base

This can now be simplified with:

[ ]:
def _getuserbase():
    if env_base := os.environ.get("PYTHONUSERBASE", None):
        return env_base

Multiple nested if, such as in cpython/Lib/copy.py, can also be avoided. This

[ ]:
from copyreg import dispatch_table
[ ]:
def copy(x):
    cls = type(x)
    reductor = dispatch_table.get(cls)
    if reductor:
        rv = reductor(x)
    else:
        reductor = getattr(x, "__reduce_ex__", None)
        if reductor:
            rv = reductor(4)
        else:
            reductor = getattr(x, "__reduce__", None)
            if reductor:
                rv = reductor()
            else:
                raise Error(
                    "un(deep)copyable object of type %s" % cls)

becomes that:

[ ]:
def copy(x):
    cls = type(x)
    reductor = dispatch_table.get(cls)
    if reductor := dispatch_table.get(cls):
        rv = reductor(x)
    elif reductor := getattr(x, "__reduce_ex__", None):
        rv = reductor(4)
    elif reductor := getattr(x, "__reduce__", None):
        rv = reductor()
    else:
        raise Error("un(deep)copyable object of type %s" % cls)

Positional-only parameters#

In Python 3.8 a function parameter can be specified position-related with /. Several Python functions implemented in C do not allow keyword arguments. This behavior can now be emulated in Python itself, e.g. for the pow() function:

[ ]:
def pow(x, y, z=None, /):
    "Emulate the built in pow() function"
    r = x ** y
    return r if z is None else r%z

f-strings support = for self-documenting expressions and debugging#

[ ]:
user = 'veit'
member_since = date(2012, 1, 30)
f'{user=} {member_since=}'

Debug and release build use the same ABI#

So far, a consistent application binary interface (ABI) should be guaranteed by Spack. However, this did not include using Python in the debug build. Python 3.8 now also supports ABI compatibility for debug builds. The Py_TRACE_REFS macro can now be set with the ./configure --with-trace-refs option.

New C API#

PEP 587 adds a new C API for configuring the Python initialisation, which offers more precise control of the entire configuration and better error reports.

Vectorcall – a fast protocol for CPython#

The protocol is not yet fully implemented; this will probably come with Python 3.9. However, you can already get a full description in PEP 590.

Update – or not?#

The following is a brief overview of the problems you may encounter when switching to Python 3.8:

Missing packages#

Bugs#

  • Python 3.7.1 was released 4 months after the first major release with a long list of bug fixes . Something similar is to be expected with Python 3.8.

Syntax#

  • Very few code analysis tools and autoformatters can already handle the syntax changes of Python 3.8

Why update anyway?#

Since the upgrade will take some time, it can be tempting to postpone the move indefinitely. Why should you concern yourself with incompatibilities in new versions when your current version works reliably?

The problem is that your Python is not supported indefinitely, nor will the libraries you use will support all older Python versions indefinitely. And the longer you delay an update, the bigger and riskier it will be. Therefore, the update to the new major version of Python is usually recommended a few months after the first release.

Porting#