Meine Python-Kollegen bekommen bald etwas, das wir seit ungefähr PHP 5.3 gar nicht mehr bewusst wahrnehmen: Code, der erst lädt, wenn man ihn anfasst. Python 3.15 erscheint am 1. Oktober mit PEP 810, expliziten Lazy Imports, und beim Lesen der Spezifikation kam ich mir vor, als würde ich Composers Babyfotos durchblättern. Also gleich meine These: Das neue Keyword wird gut funktionieren, der globale Schalter wird jemandem wehtun, und der Unterschied zwischen beidem liegt in einer Regel, die unser Ökosystem so lange verinnerlicht hat, dass wir vergessen haben, dass es je eine Regel war.

terminal
python -X importtime -c "import pandas"

Erst die Mechanik. Der Steering Council hat PEP 810 am 3. November 2025 einstimmig angenommen, vier Stimmen, Co-Autor Pablo Galindo Salgado hat nicht mitgestimmt, und Release Candidate 2 kam am 1. September. Du schreibst lazy import pandas oder lazy from json import dumps, der Name bekommt einen Platzhalter, und Python führt den echten Import erst aus, wenn dieser Platzhalter zum ersten Mal benutzt wird. Jeder PHP-Entwickler erkennt das Muster auf den ersten Blick. Das ist spl_autoload_register im Kostüm eines Soft Keywords.

Und hier ist der Grund, warum Autoloading uns nie so gebissen hat, wie es das theoretisch gekonnt hätte. PSR-4 kam mit einer ungeschriebenen Begleitregel: Eine Datei, die eine Klasse definiert, tut sonst nichts. Keine Seiteneffekte, nur eine Deklaration. So eine Datei kann jetzt oder in zehn Minuten geladen werden, das Programm merkt keinen Unterschied. Python-Module sind vom Design her das Gegenteil. Ein Import führt das Modul von oben bis unten aus, und ausgereifte Bibliotheken bauen genau auf diesen Moment, für Plugin-Registrierung und Monkey-Patching. Verschiebst du diese Ladevorgänge, hast du Seiteneffekte quer durch den ganzen Prozess neu sortiert.

Die Autoren von PEP 810 verstehen das offensichtlich, und deshalb ist das Keyword hart eingezäunt: nur auf Modulebene, verboten in Funktionen, Klassenkörpern, try-Blöcken und bei import *. Das try-Block-Verbot schmerzt am meisten, weil es den klassischen Optional-Dependency-Tanz ausschließt, bei dem du pyarrow zu importieren versuchst, den ImportError abfängst und auf einen None-Sentinel zurückfällst. Mit Deferral würde der Fehler erst bei der ersten Benutzung auftauchen, lange nachdem die umgebende except-Klausel fertig damit war, nichts zu tun, das Verbot ist also ehrliches Engineering. Die Trostpreise sind auch ordentlich: Wenn ein aufgeschobener Import explodiert, zeigt die Exception-Kette sowohl auf die Deklarationsstelle als auch auf den Zugriff, der ihn ausgelöst hat, und ein fehlgeschlagener Ladevorgang wird beim nächsten Zugriff erneut versucht.

Bei den versprochenen Gewinnen halte deine Skepsis warm. Die PEP nennt Startzeit-Reduktionen von 50 bis 70 Prozent und Speicherersparnisse von 30 bis 40 Prozent, ohne eine der Zahlen an eine benannte Codebasis zu heften; der eine zugeordnete Fall, Christian Tismers Arbeit an PySide, landet bei 10 bis 20 Prozent. Metas Instagram und Hudson River Trading werden als Produktionsnutzer genannt, ohne Zahlen dazu. Das Rohmaterial ist real genug. Auf CPython 3.11 kostet ein warmer import pandas grob 250 Millisekunden, NumPy allein etwa 64, und ein leerer Interpreter läuft in unter 3 los. Ob eine Viertelsekunde zählt, hängt komplett davon ab, wie lange der Prozess lebt. In einem CLI, das jemand den ganzen Tag benutzt, zählt sie sehr. In einem Worker, der einmal bootet und dann eine Woche lang eine Queue abarbeitet, verschwindet sie, aus demselben Grund, aus dem Laravel Octane die Boot-Kosten des Frameworks irrelevant macht, indem es sie genau einmal bezahlt.

Jetzt der Teil, der ein Change-Review-Ticket verdient. PEP 810 bringt drei Modi mit, normal, all und none, einstellbar über sys.set_lazy_imports(), das Flag -X lazy_imports oder die Umgebungsvariable PYTHON_LAZY_IMPORTS, dazu einen Filter-Hook in sys.set_lazy_imports_filter() und ein Set sys.lazy_modules, das die Namen verfolgt, die noch nicht materialisiert wurden. Modus all verschiebt jeden Import im Prozess, auch die in Dependencies, deren Maintainer Deferral nie getestet haben und die sich teils ausdrücklich auf Ausführung zur Importzeit verlassen. Die PEP sagt diesen Maintainern, wie der Fix aussieht: keine Registrierungsarbeit mehr zur Importzeit, stattdessen eine explizite init-Funktion anbieten. Das ist genau die Disziplin, für die PHP Jahre und einen Paketmanager gebraucht hat, bis sie flächendeckend war, und Python fordert sie rückwirkend ein, während es jedem Ops-Team eine einzelne Variable in die Hand drückt, die so tut, als wäre die Arbeit schon erledigt.

Wo ich also lande, nachdem ich die wirklich guten Teile anerkannt habe: Das Opt-in-Keyword ist sauber designt, und die schweren Imports am Anfang eines CLI-Einstiegspunkts zu markieren und dann das Delta mit -X importtime zu prüfen, ist geschenktes Geld, das du einsammeln solltest. Aber behandle Modus all so, wie du in einem laufenden Shop den Autoloader austauschen würdest, und halte ihn von jedem Job fern, der Daten schreibt. Ein eager Import, der fehlschlägt, beendet den Prozess, bevor irgendeine Arbeit beginnt, ein sauberer Neustart. Ein aufgeschobener kann fehlschlagen, nachdem schon Zeilen rausgegangen sind, und kein Cold-Start-Diagramm rechtfertigt es, dieses Aufräumen zu erben.

Womit wir bei dir wären. Stell dir vor, wir bekämen morgen das Spiegelbild: eine einzige Env-Variable, die jedes require in vendor/ lazy macht, Seiteneffekte hin oder her. Würdest du sie auf einer Produktionsmaschine umlegen, für einen schnelleren Boot? Falls deine Antwort Nein ist, will ich hören, welcher Beleg deine Meinung ändern würde, denn irgendwo in deiner Firma ist ein Python-Team gerade dabei, genau diese Wette einzugehen.