Python 3.13 Preview: A Modern REPL

Python 3.13 Preview: A Modern REPL

by Geir Arne Hjelle Sep 25, 2024 basics python

One of Python’s strong points is its interactive capabilities. By running python you start the interactive interpreter, or REPL, which allows you to perform quick calculations or explore and experiment with your code. In Python 3.13, the interactive interpreter has been completely redesigned with new modern features.

Python’s REPL has remained largely unchanged for decades. Instead, alternative interpreters like IPython, bpython, and ptpython have addressed some of the built-in REPL’s shortcomings, providing more convenient interactive workflows for developers. As you’re about to learn, Python 3.13 brings many significant improvements to the interactive interpreter.

In this tutorial, you’ll:

  • Run Python 3.13 and explore the new REPL
  • Browse through the help system
  • Work with multiline statements
  • Paste code into your REPL session
  • Navigate through your interpreter history

The upgraded REPL is just one of the new features coming in Python 3.13. You can read about all the changes in the what’s new section of Python’s changelog. Additionally, you can dig deeper into the work done on free threading and a Just-In-Time compiler.

A New Interactive Interpreter (REPL) in Python 3.13

To try out the new REPL for yourself, you need to get your hands on a version of Python 3.13. Before the official release in October 2024, you can install a pre-release version. After October 2024, you should be able to install Python 3.13 through any of the regular channels.

A REPL, or a Read-Eval-Print Loop, is a program that allows you to work with code interactively. The REPL reads your input, evaluates it, and prints the result before looping back and doing the same thing again.

In any version of Python, you can start this interactive shell by typing the name of your Python executable in your terminal. Typically, this will be python, but depending on your operating system and your setup, you may have to use something like py or python3 instead.

Once you start the REPL in Python 3.13, you’ll see a small but noticeable difference. The familiar Python interactive shell prompt, consisting of three right angle brackets (>>>), is now colored differently from the rest of the text:

The new REPL in Python 3.13 shows a colored prompt

The color difference indicates that the shell now supports color. In the new shell, color is mainly used to highlight output in tracebacks. If your terminal doesn’t display color, then the new REPL will automatically detect this and fall back to its plain, colorless display.

If you prefer to keep your interpreter free of color even when it’s supported, you can disable this new feature. One option is to set the new environment variable PYTHON_COLORS to 0:

Shell
$ PYTHON_COLORS=0 python
Python 3.13.0rc2 (main, Sep 13 2024, 17:09:27) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Setting PYTHON_COLORS=0 disables color in the REPL. If you set the environment variable to 1, you’ll get the colored prompt and output. However, since it’s the default, this is rarely necessary.

Before going any further, you’ll exit the REPL. As you may know, the old REPL, that you’ve used on Python 3.12 and earlier, has been widely commented on for the following idiosyncrasy:

Python
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit

The shell clearly understands your intention to end the session. Still, it makes you jump through hoops and add parentheses to your command. In Python 3.13, the REPL now understands special commands that you can write without any parentheses:

  • exit or quit: Exit the interpreter
  • help or F1: Access the help system
  • clear: Clear the screen

Having these commands more easily available is a small thing, but it removes some friction when using the interactive interpreter. You can still use parentheses and type something like exit() if you prefer. These commands are not reserved though. That means that you could shadow them with variable assignments:

Python
>>> exit = True
>>> exit
True
>>> exit()
Traceback (most recent call last):
  ...
TypeError: 'bool' object is not callable

>>> del exit
>>> exit

Here you create a variable named exit, effectively disabling the exit command. To end your REPL session, you can either delete the exit variable or use one of the alternative ways to exit the interpreter.

You have the new REPL up and running. Now it’s time to play with it and explore its new features.

Use the REPL Effectively

At its most basic, the REPL is an advanced calculator. You can enter any valid Python expression and immediately get your answer:

Python
>>> 3 * 13
39
>>> (6048 + 1729)**2
60481729

Here, you’ve calculated 3 × 13 and (6048 + 1729)². One significant convenience is that the REPL immediately prints the result. You don’t need to explicitly call print() like you would in a script.

To take advantage of having Python at your fingertips, you can also import libraries and call functions inside those libraries. For example, you can use math for more advanced calculations or use some of the built-in string methods:

Python
>>> import math
>>> math.cos(2 * math.pi)
1.0

>>> headline = "python 3.13"
>>> headline.title()
'Python 3.13'
>>> headline.title().center(20)
'    Python 3.13     '
>>> headline.title().center(20, "-")
'----Python 3.13-----'

Here, you’ve used cos() and pi from the math module in the standard library. You’ve also used a few string methods to format a simple headline.

One challenge when working with modules, functions, and methods is remembering their names. A feature that assists with this is tab-completion. This allows you to hit the Tab key on your keyboard and get suggestions for how to complete a command. In the new REPL, the tab-completion has been improved:

Note that the completions disappear when they’re no longer relevant. This is in contrast to earlier, where the suggestions would stick around and add noise to your session.

The tab-completion feature is still limited to evaluated objects. For example, you won’t get any suggestions if you hit Tab after typing headline.title().c because the REPL doesn’t evaluate .title(), so it doesn’t know that it returns a string. It doesn’t help that you manually evaluated it on the line before.

One convenience when working interactively is that Python will continually assign the latest result to the special underscore variable (_):

Python
>>> headline = "python 3.13"
>>> headline.title()
'Python 3.13'
>>> _.center(20, "-")
'----Python 3.13-----'

In the highlighted line, you use underscore (_) to refer to your title-cased headline evaluated earlier. One advantage of this is that you can use tab-completion to spell out .center().

You’ve seen how you can use tab-completion to help you recall the names of functions and methods and enter your code more effectively. Next, you’ll see how Python 3.13 can help you with more than just names.

Get Help From Python

The Python REPL comes with a help() function that you can use to access Python’s built-in help system. In the new REPL, you can more quickly access the help browser with F1. Go ahead and press F1 on your keyboard:

Python
>>> # F1
Welcome to Python 3.13's help utility! If this is your first time using
Python, you should definitely check out the tutorial at
https://docs.python.org/3.13/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To get a list of available
modules, keywords, symbols, or topics, enter "modules", "keywords",
"symbols", or "topics".

Each module also comes with a one-line summary of what it does; to list
the modules whose name or summary contain a given string such as "spam",
enter "modules spam".

To quit this help utility and return to the interpreter,
enter "q", "quit" or "exit".

help>

When you press F1, you see some general information about Python’s help utility. After the instructions on how to use this feature, you see that the regular prompt has changed to help>. When this prompt is displayed, you can’t type expressions to evaluate them. To do so, you first need to return to the regular prompt, for example, by typing Q and hitting Enter:

Python
help> q

You've now left help and have returned to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>>

Use F1 to get back into the help system. At the help> prompt, you can type the names of modules, functions, and methods and see their help text. You can also learn about a series of other topics. To see an overview, type topics:

Python
help> topics

Here is a list of available topics.  Enter any topic name to get more help.

ASSERTION           DELETION            LOOPING             SHIFTING
ASSIGNMENT          DICTIONARIES        MAPPINGMETHODS      SLICINGS
ATTRIBUTEMETHODS    DICTIONARYLITERALS  MAPPINGS            SPECIALATTRIBUTES
ATTRIBUTES          DYNAMICFEATURES     METHODS             SPECIALIDENTIFIERS
AUGMENTEDASSIGNMENT ELLIPSIS            MODULES             SPECIALMETHODS
BASICMETHODS        EXCEPTIONS          NAMESPACES          STRINGMETHODS
BINARY              EXECUTION           NONE                STRINGS
BITWISE             EXPRESSIONS         NUMBERMETHODS       SUBSCRIPTS
BOOLEAN             FLOAT               NUMBERS             TRACEBACKS
CALLABLEMETHODS     FORMATTING          OBJECTS             TRUTHVALUE
CALLS               FRAMEOBJECTS        OPERATORS           TUPLELITERALS
CLASSES             FRAMES              PACKAGES            TUPLES
CODEOBJECTS         FUNCTIONS           POWER               TYPEOBJECTS
COMPARISON          IDENTIFIERS         PRECEDENCE          TYPES
COMPLEX             IMPORTING           PRIVATENAMES        UNARY
CONDITIONAL         INTEGER             RETURNING           UNICODE
CONTEXTMANAGERS     LISTLITERALS        SCOPING
CONVERSIONS         LISTS               SEQUENCEMETHODS
DEBUGGING           LITERALS            SEQUENCES

help> NONE
The Null Object
***************

This object is returned by functions that don’t explicitly return a
value.  It supports no special operations.  There is exactly one null
object, named "None" (a built-in name).  "type(None)()" produces the
same singleton.

It is written as "None".

You’ve asked for the list of topics. Note that these are all written in uppercase letters to distinguish them from module and function names. After you type NONE, you’ll be taken to the help page to learn more about None.

You can also ask for help about specific modules or functions. For example, to learn more about math.cos(), you type its name at the help> prompt:

Python
help> math.cos

When you ask for help like this, it brings up a screen that explains how to use the function:

Python Syntax
Help on built-in function cos in math:

math.cos = cos(x, /)
    Return the cosine of x (measured in radians).

These explanations can help you remember or discover how to use different functions, including which arguments to pass in.

When you’re working inside the help system, you don’t need to import the modules that you want information about. Instead, the help system does its own import. This means that if you have a module that does an action on import, then that side effect will happen when you ask for help:

Python
help> antigravity

The antigravity module is an Easter egg in Python related to a famous XKCD-comic. If you import this module, then your browser will open the comic. This also happens if you ask for help about the module.

You’ve seen that it’s more straightforward to get help in the new REPL. Another convenient improvement is how you enter and edit longer Python statements, as you’ll learn about next.

Work With Multiline Statements

One well-known pain point for Python’s REPL has traditionally been multiline statements. Consider the following example where you write a list comprehension over several lines:

Python
>>> numbers = range(3, 13)
>>> [
...     (number - 3)**3 for number in numbers
...     if number % 2 == 1
... ]
[0, 8, 64, 216, 512]

Essentially, you calculate a cubic based on each odd number in the original sequence. Now, say that you want to rerun the calculation, but this time use (number - 2) instead of (number - 3) as the base of the exponentiation.

In 3.13, you can restore previous lines in your history by using Up. In Python 3.12 and older, you needed to restore each of those four lines independently, which required a lot of patience and precision. The new interpreter treats each such code block as one entity and lets you recall all four lines with a single Up keystroke.

When you’re editing the list comprehension, you can use your arrow keys to navigate within the block of code and make any changes necessary. Once you’re ready to execute the block of code, you need to navigate to its last line and hit Enter. If you press Enter on other lines, Python will insert a blank line for you, allowing you to extend your code:

The new capabilities in handling multiline statements is an important improvement over the old REPL, which will make you much more efficient when exploring your code interactively.

Copy and Paste in Style

In the traditional REPL, you’ve been able to paste code that you’ve copied from elsewhere. However, it’s had some limitations. Most importantly, any blank lines in your input tended to cause havoc. There hasn’t been any special treatment of pasted code, so a blank line in a multiline statement has been treated as a second Enter and executed the half-written code.

As an example, consider the following class definition:

Python power_factory.py
class PowerFactory:
    """Create instances that can calculate powers."""

    def __init__(self, exponent):
        self.exponent = exponent

    def __call__(self, number):
        return number**self.exponent

You’ll soon see how you can use this class. But for now, read between the lines—literally! There are two blank lines in the class definition and they’ll cause some issues. This is the typical and recommended way to format such code. Next, you can hover over the code block and click to copy the code.

If you open a REPL in Python 3.12 or older and paste the PowerFactory code, you’ll see something like this:

Python
>>> class PowerFactory:
...     """Create instances that can calculate powers."""
...
>>>     def __init__(self, exponent):
  File "<stdin>", line 1
    def __init__(self, exponent):
IndentationError: unexpected indent
>>>         self.exponent = exponent
  File "<stdin>", line 1
    self.exponent = exponent
IndentationError: unexpected indent
>>>
>>>     def __call__(self, number):
  File "<stdin>", line 1
    def __call__(self, number):
IndentationError: unexpected indent
>>>         return number**self.exponent
  File "<stdin>", line 1
    return number**self.exponent
IndentationError: unexpected indent

You’re getting a small avalanche of errors. It’s a bit subtle, but in the highlighted line you can see that the REPL has returned to the regular >>> prompt. This indicates that it considers the block of code started by class as finished. In other words, the following statements will be evaluated independently of the class. The result is clearly not what you were looking for.

In Python 3.13, pasted code gets a bit of special treatment, and now the same example just works:

Python
>>> class PowerFactory:
...     """Create instances that can calculate powers."""
...
...     def __init__(self, exponent):
...         self.exponent = exponent
...
...     def __call__(self, number):
...         return number**self.exponent
...

The interactive shell treats the whole code snippet as one code block, and the class is correctly defined.

As a small aside, PowerFactory allows you to calculate different powers or exponents of numbers. For example, you can create an instance that can raise any number to the power of three:

Python
>>> cubed = PowerFactory(3)
>>> cubed(13)
2197

This tells you that 13³ or 13 × 13 × 13 equals 2,197.

Another challenge you may have run into when pasting into the old interactive interpreter is that because each line is evaluated immediately, you can’t effectively test scripts or collections of code lines. Consider the following small game:

Python guessing_game.py
import random

print("Guess my secret number!\n")
max_value = int(input("Enter maximum for the secret number: "))

print(f"Guess my number between 1 and {max_value}")
secret = random.randint(1, max_value)

while True:
    guess = int(input("Guess a number: "))
    if secret < guess:
        print(f"Sorry, my number is lower than {guess}")
    elif secret > guess:
        print(f"Sorry, my number is higher than {guess}")
    else:
        break

print(f"Yes, my number is {secret}")

This script implements a classic guessing game, where your computer comes up with a secret number that you need to guess. To help you narrow down the secret number, you’ll get helpful hints for each of your guesses.

The script is designed to run as one piece of code. Say that you want to copy the script into your REPL to test the workflow and potentially experiment with some tweaks to the code. In Python 3.12 and earlier, this simply wouldn’t work. Each line or code block is executed immediately, so you’d need to stop and enter the maximum value before pasting the rest of the script.

In Python 3.13, pasting a chunk of code like this works just as you’d expect:

Python
>>> import random
...
... print("Guess my secret number!\n")
... max_value = int(input("Enter maximum for the secret number: "))
...
... print(f"Guess my number between 1 and {max_value}")
... secret = random.randint(1, max_value)
...
... while True:
...     guess = int(input("Guess a number: "))
...     if secret < guess:
...         print(f"Sorry, my number is lower than {guess}")
...     elif secret > guess:
...         print(f"Sorry, my number is higher than {guess}")
...     else:
...         break
...
... print(f"Yes, my number is {secret}")
...
Guess my secret number!

Enter maximum for the secret number: 1000
Guess my number between 1 and 1000
Guess a number: 500
Sorry, my number is lower than 500
Guess a number: 250
Sorry, my number is higher than 250
Guess a number: 313
Yes, my number is 313

You’ve pasted your guessing game into the REPL. All lines are executed at the end, allowing the script to run as it was meant to. In the end, you’re able to figure out that the secret number was 313.

You’ll probably agree that being able to reliably paste code is another great quality-of-life improvement in the new REPL.

Look Back in History

Earlier, you saw how you can recall some of the code you recently entered with the help of Up. Python stores your history in a file, and in the Python 3.13 REPL, you can access that file by pressing F2.

If you hit F2, you open the history browser. This view shows you all the commands that you’ve entered in the interactive interpreter. The commands are kept across different sessions, so you can unearth code that you played with days and weeks ago. Just as with the help browser, the information should open in your standard pager. This means that you can navigate the file with familiar keyboard shortcuts.

The history browser gives you a quick way to look at code you’ve written before. The code is stored without any prompts and without any outputs. Therefore, you can copy the code from history with your usual shortcuts, and as you’ve seen, the new REPL allows you to paste the code back after returning to the prompt.

Once you paste the code, you can also use the multiline editing features to make any changes that you require.

Conclusion

Many of the improvements in Python 3.13 happen under the hood and are aimed at power users. The new and improved REPL is something that can benefit everyone.

If you’re a beginner, you’ll have a better experience exploring the language interactively. If you’re already using a more advanced shell like IPython or bpython, then the built-in REPL will still not be as feature-rich. However, it’s much improved, and you can always rely on it being available without needing to be installed.

In this tutorial, you’ve explored the new REPL included in Python 3.13 and:

  • Browsed through the help system
  • Worked with multiline statements
  • Pasted code into your REPL session
  • Navigated through your interpreter history

Will you be using the new REPL? Which other features in Python 3.13 are you excited about? Share your experiences in the comments.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Geir Arne Hjelle

Geir Arne is an avid Pythonista and a member of the Real Python tutorial team.

» More about Geir Arne

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!