9 Punkte von GN⁺ 2024-10-07 | 1 Kommentare | Auf WhatsApp teilen
  • HPy ist eine neue API, um Python mit C zu erweitern
  • Statt #include <Python.h> wird #include <hpy.h> verwendet

Vorteile von HPy

  • Zero Overhead auf CPython: Mit HPy geschriebene Erweiterungen laufen mit derselben Geschwindigkeit wie „normale“ Erweiterungen
  • Schneller auf alternativen Implementierungen: Läuft schneller auf PyPy, GraalPy usw.
  • Universelle Binärdateien: Mit dem HPy Universal ABI gebaute Erweiterungen können ohne Änderungen auf CPython, PyPy, GraalPython usw. geladen werden
  • Migrationspfad für die Mischung mit der alten C-API: Legacy-C-API-Aufrufe und HPy-API-Aufrufe können gemischt werden. Sobald der gesamte Code migriert ist, kann er als universelle Binärdatei kompiliert werden, die auf allen CPython-Versionen, PyPy oder GraalPy funktioniert
  • Debug-Modus: Speicherlecks, fehlerhafte Objektlebensdauern, falsche Nutzung der API usw. lassen sich leicht erkennen
  • Bessere API: Überwindet die Grenzen der Standard-Python/C-API, erzeugt konsistentere Erweiterungen mit höherer Qualität und ist so entworfen, dass Fehler schwerer entstehen
  • Evolvierbarkeit: Wie in PEP 620 gut zusammengefasst, legt die Standard-Python/C-API viele interne Implementierungsdetails offen und erschwert damit die Weiterentwicklung der C-API. HPy verbirgt alle internen Implementierungsdetails und hat dieses Problem daher nicht

Aktueller Status

  • HPy wird aktiv entwickelt. 0.9.0 ist die aktuelle Alpha-Version, wird den Alpha-Status aber bald verlassen; man arbeitet auf einen stabilen Release hin
  • Das HPy ABI gilt inzwischen als stabil genug, um in den kommenden Releases Zusagen zur binären Vorwärts- und Rückwärtskompatibilität einhalten zu können
  • Man geht davon aus, dass die API inzwischen genügend Anwendungsfälle abdeckt, um wichtige Pakete zu migrieren (insbesondere siehe den NumPy-Port)
  • Es gibt auch einen Porting Guide und umfangreiche Dokumentation, insbesondere eine API-Referenz
  • Für Design-Diskussionen und neue Anforderungen ist das Projekt jederzeit offen

HPy-kompatible Erweiterungen

  • ultrajson-hpy: Das erste echte Modul, das auf HPy portiert wurde
  • piconumpy: Wie der Name schon sagt, ein minimales NumPy-ähnliches Modul zur Definition benutzerdefinierter Typen
  • numpy: Eines der ehrgeizigen Ziele ist es, NumPy auf HPy zu portieren und diese Erfahrung zu nutzen, um besser zu verstehen, wie die API gestaltet werden sollte. Dieser Port steht kurz davor, die Test-Suite zu bestehen
  • matplotlib: Wegen der Abhängigkeit von NumPy ist die Migration in den Universal-Modus noch nicht vollständig abgeschlossen. Damit in HPy weiterhin Legacy-C-API-Funktionen aufgerufen und die Test-Suite erfolgreich ausgeführt werden kann, bietet HPy eine Legacy-Kompatibilitäts-API
  • kiwi-solver: Eine Abhängigkeit von Matplotlib, die vollständig in den Universal-Modus portiert wurde

Meinung von GN⁺

  • HPy ist ein sehr vielversprechendes Projekt, das die Grenzen der Python/C-API überwindet und bessere Erweiterbarkeit sowie Portabilität bietet
  • Besonders attraktiv ist das große Potenzial für Leistungssteigerungen auf alternativen Python-Implementierungen wie PyPy und GraalPy
  • Die Migration von der Legacy-C-API kann zwar schwierig sein, aber HPy bietet einen schrittweisen Migrationspfad, der diesen Prozess deutlich besser handhabbar macht
  • Bei der Einführung von HPy sollten die Integration in bestehende Build-Systeme und Deployment-Pipelines, die Akzeptanz durch Upstream-Projekte sowie der Reifegrad und die Stabilität von HPy selbst berücksichtigt werden
  • Andere Projekte mit ähnlichen Zielen wie HPy sind Cython und Rusts PyO3. Sie unterscheiden sich von HPy dadurch, dass sie statt einer Low-Level-C-API höherstufige Sprachen verwenden

1 Kommentare

 
GN⁺ 2024-10-07
Hacker-News-Kommentare
  • Der lästigste Teil bei der Arbeit mit der C API ist das Einrichten der Compile-/Linker-Flags. python3-config funktioniert nur auf OS-Ebene und ist schwer zu verwenden, um auf per pip installierte Pakete zuzugreifen. python3 -m venv erzeugt solche Skripte nicht, und auch anaconda/miniconda ist problematisch. Jedes Paket verschmutzt seine Build-Skripte mit hartcodierten python3 -c "import sys: print..."-Aufrufen. Ich habe einen PR eröffnet, um CPython ein Flag python3 -m sysconfig --json hinzuzufügen

  • Dass sich die Python-Sprache zu stark auf eine einzelne Implementierung konzentriert, könnte ihren langfristigen Erfolg gefährden. Webserver, Kommandozeilenprogramme und Embedded-Geräte haben unterschiedliche Anforderungen. Wenn es diesem Projekt gelingt, die C API von Python durch etwas zu ersetzen, das keine Implementierungsdetails offenlegt, könnte es leichter werden, alternative Implementierungen zu pflegen und mit neuen Technologien zu experimentieren

  • Ich frage mich, ob dieses Projekt versionsunabhängige Python-Bindings bereitstellt. Derzeit bauen wir Bindings für jede Version separat, was viel CI/CD-Zeit verbraucht

  • Ein Benchmark, der HPy-Erweiterungen und Cython-/pybind11-Implementierungen hinsichtlich Performance und Entwicklungszeit vergleicht, wäre interessant

  • Mir ist nicht klar, wie dieses Projekt mit Bibliotheken wie PyBind11 oder nanobind zusammenspielt. Es scheint, als müsste man neu schreiben, um solche Bibliotheken auf dieselbe Weise zu nutzen

  • Ich frage mich, wie viele neue Erweiterungen heutzutage noch in C geschrieben werden. Ich dachte, es seien hauptsächlich Dinge wie Boost Python, pybind und PyO3

  • Ich poste häufig über die Implementierung von CPython-Bindings mit minimalem Overhead und möchte ein paar Empfehlungen, Fragen und Bedenken teilen. Es wäre gut, die Landingpage und die README des Repositories des HPy-Projekts neu zu strukturieren. Unterstützende Statistiken zu PyPy, GraalPython und anderen Python-Runtimes würden es überzeugender machen

  • Die Verwendung eines gekapselten Kontextobjekts wie HPyContext ist nützlich für eine zukünftige multithreaded Python-Welt oder komplexe Umgebungen. Wenn HPyContext jedoch auf den Singleton von CPython umgeleitet wird, löst das das Problem nicht

  • Der Benchmark von 2019 erwähnt die Aufrufkonvention METH_FASTCALL von CPython, vergleicht sie aber nicht. Wenn Performance wichtig ist, ist es besser, Argumente direkt aus dem Tupel zu parsen, ohne String-Formatter zu verwenden

  • Ich frage mich, ob es in Python etwas Einfaches wie das ffi von luajit gibt, bei dem man C-Header übergibt und eine Shared Library lädt, um Strukturen nutzbar zu machen und Funktionen aufzurufen

  • Ich interessiere mich dafür, Go aus Python heraus aufzurufen, und gopy erzeugt Python-Bindings für cgo. HPy<->cgo könnte weniger Overhead haben

  • Stellt euch vor, wie anders das Python-Ökosystem heute wäre, wenn diese Arbeit schon vor 20 Jahren abgeschlossen worden wäre