Pendulum baut den wohl verfluchtesten „+“-Operator in ganz Python
Why Pendulum had to write the most cursed "+" operator in all of Python
Pendulum verspricht DST-sichere Arithmetik und Drop-in-Kompatibilität mit datetime. Der Konflikt zeigt sich im „+“-Operator: Er inspiziert den Call-Stack, um zu erraten, ob der Aufrufer die Standard-Semantik erwartet. Das ist nicht nur fragil, sondern auch rund 600-mal langsamer als die Standardbibliothek. Ein kürzlich gemergter Pull-Request entschärft den Hack, doch das Grundproblem bleibt: Als Subklasse kann Pendulum nicht beide Versprechen halten.
„Der `+`-Operator von Pendulum ist ungewöhnlich, selbst für eine Datetime-Bibliothek: Wenn man ein `timedelta` zu einem Pendulum-`DateTime` addiert, konsultiert er den Call-Stack, um zu entscheiden, welche Antwort er gibt.“
- shoo
Mmm. Den Kontrollfluss basierend auf Introspektion des Call Stacks zu ändern, ist ziemlich übel.
Ich erinnere mich, dass wir in einem Projekt eine nette Verwendung für Call-Stack-Introspektion gefunden haben – nicht um den Kontrollfluss zu ändern, sondern um das Logging zu verbessern. Innerhalb einer Hilfsfunktion open_db_connection, um automatisch einen informativen Namen zu generieren, der beschreibt, welcher Teil der Codebasis die Verbindung geöffnet hatte:
Z.B. some_backend_process: main -> ... > grandparent -> parent -> open_db_connection
Wir nutzten Informationen aus dem Call Stack, um einen String "some_backend_process grandparent.parent" zu erzeugen, der die Aufrufstelle beschreibt und beim Herstellen einer Verbindung als application_name [1] an postgres übergeben werden konnte. Dann hatten wir von der Datenbankseite aus, falls zur Laufzeit problematische Abfragen auftraten, viel mehr Anhaltspunkte, um herauszufinden, welcher Teil der Backend-Codebasis dafür verantwortlich war [2].
Es gäbe eine Möglichkeit, etwas Äquivalentes zu tun, ohne in den Call Stack zu schauen, indem man vom Aufrufer verlangt, explizit einen beschreibenden und eindeutigen Namen zu übergeben, aber das macht die Sache etwas fehleranfälliger, besonders da einige Entwickler dazu neigen, Teile von vorhandenem Code zu kopieren und überall denselben Namen wiederzuverwenden.
[1] https://www.postgresql.org/docs/current/libpq-connect.html#L...
[2] https://www.postgresql.org/docs/current/monitoring-stats.htm...
- jvolkman
Ich setze noch einen drauf mit meinem Hack, der den Wert von `sys.platform` je nach Aufrufer ändert: https://github.com/jvolkman/rules_pycross/blob/main/pycross/...
Das wird beim Cross-Kompilieren von Binary-Wheels verwendet (z.B. beim Bauen eines macOS-Wheels auf einem Linux-Build-Host oder umgekehrt).
- ariebovenberg
Hier der Autor. Ich bin darauf gestoßen, als ich Pendulum mit `whenever` verglichen habe, der datetime-Bibliothek, die ich betreue. Ich habe einen Patch geschickt, der den Hack entfernt, aber in dem Beitrag geht es darum, warum das zugrunde liegende Design nicht auf dieselbe Weise gepatcht werden kann. Ich beantworte gerne Fragen.