Python 3.13 - New Features & Deprecations

Sadra YahyapourSadra Yahyapour
5 min read

We introduced several cool typing and interactive interpreting features in Python 3.12. I discussed all of them here:

Before we go ahead, this is the full patch note about this new release.
The biggest change introduced in the early 3.13 patch notes is that the Global Interpreter Lock (GIL) is now droppable, and you can disable it in certain cases!

1. GIL & JIT

CPython will run with the GIL disabled when configured using the --disable-gil option at build time. To check if the current interpreter is configured with --disable-gil, run the following command:

... -c "import sys; sysconfig.get_config_var('Py_GIL_DISABLED')"

What's more, there will be an experimental version of a just-in-time compiler (JIT) that is disabled by default. You can use as easy as passing an option or by creating your own specific build of CPython 3.13.

It's been quite a while since PyPy introduced its high-performance garbage collector along a JIT compiler. These features have shown great promises.

All of this leads us to realize that CPython 3.14 will be a significant performance improvement, not only for users but also for all frameworks built on top of Python.

Now, without further ado, let's talk about some of the changes.

2. A Better Interactive Interpreter

The new interpreter provides more detailed error messages and tracebacks, helping you catch bugs and issues even faster. They are more colorful. You can disable this behavior by setting PYTHON_COLORS and NO_COLOR environment variables.

PYTHON_COLORS=0 python3.13 main.py

If you write a script inside a .py file with a file name similar to one of the standard library names, such as random, you would typically get a circular import error.

$ python3.12 random.py
Traceback (most recent call last):
  File "/home/random.py", line 1, in <module>
    import random; print(random.randint(5))
    ^^^^^^^^^^^^^
  File "/home/random.py", line 1, in <module>
    import random; print(random.randint(5))
                         ^^^^^^^^^^^^^^
AttributeError: partially initialized module 'random' has no attribute 'randint' (most likely due to a circular import)

But now, you get a more precise exception.

$ python3.13 random.py
Traceback (most recent call last):
  File "/home/random.py", line 1, in <module>
    import random; print(random.randint(5))
    ^^^^^^^^^^^^^
  File "/home/random.py", line 1, in <module>
    import random; print(random.randint(5))
                        ^^^^^^^^^^^^^^
AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/random.py' since it has the same name as the standard library module named 'random' and the import system gives it precedence)

The same rule applies to third-party packages.

If you call a function with an incorrect parameter name, the interpreter will guess what you meant and suggest the correct name.

>>> "better error messages!".split(max_split=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    "better error messages!".split(max_split=1)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?

3. No More Functions in REPL

Now, you can call help(), exit(), and quit() commands without the parentheses.

4. Deprecation Warnings

The warning standard library is used to alert developers about deprecations, future removals, and similar issues. In Python 3.13, there is a @deprecation decorator that allows you to add deprecation warning messages to any of your components.

from warnings import deprecated

@deprecated("Use PayPalPaymentProcessor instead")
class PaymentProcessor:
    ...

class PayPalPaymentProcessor:
    ...

Once a user tries to use any of the deprecated components, a warning will appear in the prompt. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses.

5. New Typing Features

We all know that Python itself doesn't enforce types. You can define a function that takes a parameter name: str and still pass an integer to that function. So, working on the typing module means improving static type checkers even more, and you should use them.

ReadOnly type

In Python 3.13, we have typing.ReadOnly, which can be applied to items of a TypedDict to make them read-only. If you try to change the item value, you can, but your type checker should raise an error.

class Student(TypedDict):
   idn: ReadOnly[str]
   gpa: float

def modify_student(s: Student) -> None:
   s["gpa"] = 4.0  # allowed
   s["idn"] = "24315"  # typechecker error

TypeIs type

This type is assigned to the return value of callables (like functions) that return booleans, indicating whether a variable is an object of a specific type or not.

Consider the following simple function.

def is_student(s: Student):
    return isinstance(s, Student)

Similar to typing.List and typing.Union, it accepts any generic or custom types, so you should use it like TypeIs[SomeType]. Now, let's add a type hint to the return value of that function using TypeIs.

from typing import TypeIs

def is_student(s: Student) -> TypeIs[Student]:
    return isinstance(s, Student)

Now, if is_student(val) returns True, the type checker knows that val is of type Student. If it returns False, the type checker knows that val is not of type Student.

Generally speaking, you should use it when..

  • The function returns a boolean value.

  • The function checks an object's type using isinstance() or any other mechanism.

6. Official Support for iOS & Android

Python 3.13 is going to have a separate official release for the iOS platform. The team is working on the Android one as well, but not planned for the 3.13 release.

7. Version Support

  • Python 3.9 - 3.12 have one and a half years of full support, followed by three and a half years of security fixes.

  • Python 3.13 and later have two years of full support, followed by three years of security fixes.

Python 3.14, 3.15, and 3.16 Expected Removals

We're going to see many removals as some components in the standard library are deprecated. Here, I've listed the libraries most affected by these future component removals.

  • argparse

  • asyncio

  • pathlib

  • importlib

Conclusion

GIL has been both a blessing and a mess, in my opinion. It's great to see the community moving forward, considering alternatives and solutions for allowing users to optionally use the components. I'm confident that the JIT compiler will make Python even faster in the next few releases. There will be significant performance improvements in high-scale web frameworks like Django. I hope this article has given you a clear insight into the upcoming Python 3.13 release.

0
Subscribe to my newsletter

Read articles from Sadra Yahyapour directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sadra Yahyapour
Sadra Yahyapour

A passionate software developer who enjoys sharing his thoughts with others and learning from them vise versa!