Python 3.13 mit verbesserter Shell

  Ralf Hersel   Lesezeit: 3 Minuten  🗪 4 Kommentare Auf Mastodon ansehen

Mit der Version 3.13 der beliebten Programmiersprache ist die interaktive Shell erheblich verbessert worden und ist noch praxisgerechter.

python 3.13 mit verbesserter shell

Diese Artikelidee steht schon seit einer Weile auf meiner Aufgabenliste. Nachdem vor wenigen Tagen Python 3.13 in meinem Manjaro angekommen ist, kann ich ihn endlich schreiben. Neben anderen Verbesserungen, wie dem abschaltbaren Global Interpreter Lock, um Multithreading-Anwendungen effizienter laufen zu lassen, und einem experimentellen Just-in-Time-Compiler, begeistert mich die verbesserte interaktive Shell.

Für alle, die sich nicht mit Python auskennen, möchte ich kurz erklären, worum es sich bei der interaktiven Shell handelt. Wer ein Pythonprogramm/-skript schreiben möchte, erstellt üblicherweise den Quellcode in einem Texteditor oder einer IDE, speichert den Code und führt ihn mit dem Python-Interpreter aus, z. B. python meincode.py

Während man so vor sich hin programmiert, ist es manchmal nützlich, ein bestimmtes Code-Statement (oder mehrere) auszuprobieren. Der oben beschriebene Weg ist dafür viel zu umständlich. An dieser Stelle kommt die interaktive Shell ins Spiel. Diese kann man in einem Terminal durch Eingabe von python starten und darin arbeiten.

Interaktive Shell

Im Screenshot sieht man ein Beispiel, wie man schnell etwas ausprobieren kann. Ich vergesse gerne, wie Slicing funktioniert, also das Auslesen eines bestimmten Teils einer Liste. Nun habe ich eine Liste a mit 10 Elementen erstellt und probiere aus, wie man die letzten beiden Elemente ausliest: a[-2:]

Bisher war die Shell zeilenorientiert. Seit Python 3.13 unterstützt sie mehrzeiliges Editieren, wodurch sie sich viel mehr wie ein Editor anfühlt.

Mehrzeiliges Editieren

Sehr praktisch ist auch der neue History Browsing Modus, den man mit F2 einleitet. Darin wird die History angezeigt und die Prompt-Zeichen (>>>, ...) ausgeblendet. Somit ist es viel einfacher, Code aus der Shell zu kopieren; man erspart sich das nachträgliche Entfernen der Promp-Zeichen.

History Browser

Genauso praktisch ist der Paste-Modus, der mit F3 aufgerufen wird. Dieser ermöglicht das einfache Hineinkopieren von Code-Blöcken. Eine weitere Verbesserung ist der Help-Modus, den man durch die Eingabe von help in der Shell aufruft. Darin kann man Hilfe zu Befehlen und Modulen aufrufen. Zu guter Letzt kann die Shell jetzt mit exit beendet werden, statt wie bisher nur mit Strg+Z.

Titelbild: https://pixabay.com/photos/snake-python-serpent-scales-543243/

Quelle: https://blog.python.org/2024/10/python-3130-final-released.html

Tags

Python, SHELL, Interactive

Ralf Hersel Admin
Geschrieben von Ralf Hersel am 7. Februar 2025 um 21:08

Das ist ein Test.

Das ist fett.

Das ist # Titel

Das ist kursiv

> Das ist ein Zitat.

Nun kommt ein Code-Block:

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = GUI()
    MainWindow.show()
    sys.exit(app.exec_())

Das ist eine Bullet-List:

  • Apfel
  • Birne
  • Orange

Das ist eine Aufzählung:

  1. Apfel
  2. Birne
  3. Orange

Ein Link: GNU/Linux.ch

Ein Bild: Irgendein Bild

Preview-Test:

Ralf Hersel Admin
Geschrieben von Ralf Hersel am 7. Februar 2025 um 21:27

Das ist ein Titel

Ralf Hersel Admin
Geschrieben von Ralf Hersel am 7. Februar 2025 um 21:28

Titeltest

Das ist ein Titel

Ende Titeltest

Ralf Hersel Admin
Geschrieben von Ralf Hersel am 14. Februar 2025 um 21:15

Zweiter Test von Ralf

Subtitle

Das ist ein normaler Text. Das auch. Nun folgt eine Aufzählung:

  • Apfel
  • Birne

Es folgt eine Nummerierung:

  1. Apfel
  2. Birne

Nun teste ich einen Link: https://fsfe.org/

Und ein Image:

Hier ist ein schwieriger Codeblock:

import re
from functools import reduce
from typing import List, Tuple, Dict

class ComplexDataProcessor:
    def __init__(self, data: List[Dict[str, Any]]):
        self.data = data

    def process(self) -> Tuple[Dict[str, float], List[str]]:
        filtered_data = filter(lambda x: x['value'] > 0 and 'category' in x, self.data)

        result = reduce(
            lambda acc, item: {
                **acc,
                item['category']: acc.get(item['category'], 0) + item['value']
            },
            filtered_data,
            {}
        )

        anomalies = [
            f"Anomaly in {item['id']}: {item['value']}"
            for item in self.data
            if item['value'] < 0 or 'category' not in item
        ]

        return result, anomalies

    @staticmethod
    def validate_input(input_string: str) -> bool:
        pattern = r'^[A-Za-z0-9_\-]+$'
        return bool(re.match(pattern, input_string))

if __name__ == "__main__":
    sample_data = [
        {"id": "A1", "category": "fruit", "value": 10.5},
        {"id": "B2", "category": "vegetable", "value": 7.25},
        {"id": "C3", "value": -5.0},
        {"id": "D4", "category": "fruit", "value": 3.75},
    ]

    processor = ComplexDataProcessor(sample_data)
    processed_result, found_anomalies = processor.process()

    print(f"Processed result: {processed_result}")
    print(f"Anomalies found: {found_anomalies}")

    test_input = "Valid_Input-123"
    print(f"Input validation: {processor.validate_input(test_input)}")

Ende des Tests.