Das Beste aus beiden Welten Rust mit Python miteinander kombinieren

Von Dipl. Betriebswirt Otto Geißler Lesedauer: 4 min |

Anbieter zum Thema

Die Bibliotheken der Sprachen Python und Rust ermöglichen es, den Komfort von Python mit der Geschwindigkeit von Rust zu vereinen. Welche weiteren Vorteile ergeben sich daraus? Und was ist dabei zu beachten?

Eine Kombination aus Rust und Python – oder Python und Rust – kann die Vorteiler beider Programmiersprachen vereinen.
Eine Kombination aus Rust und Python – oder Python und Rust – kann die Vorteiler beider Programmiersprachen vereinen.

Jede Programmiersprache hat ihre eigenen Stärken und Schwächen. Python bietet viele praktische Spezifikationen, ist jedoch rechentechnisch etwas langsam. Rust liefert hingegen eine ordentliche Geschwindigkeit auf Maschinenebene und hohe Speichersicherheit, ist allerdings wiederum komplexer als Python.

Die gute Nachricht: Beide Sprachen lassen sich gut kombinieren. Das heißt, Entwickler können von der Benutzerfreundlichkeit von Python als auch von der Geschwindigkeit und Leistungsfähigkeit von Rust profitieren.

Argumente für Python

Wenn Entwickler und Entwicklerinnen ein Softwareprojekt starten, stehen sie vor der Wahl, welche Programmiersprache sie verwenden möchten. Python gehört beispielsweise zu den beliebtesten und universellsten Sprachen. Dennoch gibt es Einschränkungen. Was ist für den Einsatz von Python zu beachten?

Geschwindigkeit

Die dynamische Natur von Python bedeutet auch, dass es für manche Aufgaben sehr langsam sein kann und bei parallelen Berechnungen nicht besonders effektiv ist. Möglicherweise möchten Entwickler leistungskritischen Code doch in einer niedrigeren Sprache schreiben.

Wiederverwendbarkeit

Warum Portcode, wenn man ihn direkt nutzen kann? Teile von NumPy/SciPy sind schließlich immer noch in Fortran geschrieben.

Kooperation

Wenn ein Team Python und ein anderes Rust schreibt, müssen sie den Code des anderen verwenden.

Migration

Angenommen, man müsste aus einem besonderen Grund die gesamte Python-Codebasis in Rust neu schreiben, dann wäre das Modul für Modul möglich.

Wenn es nur um die Geschwindigkeit geht, könnten Entwickler Cython oder die Bibliothek Numba verwenden, die den Python-Code in etwas anderes neu kompilieren würde. Möchten sie jedoch mehr Kontrolle haben oder andere Ziele verfolgen, müssten sie über eine Erweiterung nachdenken. Der klassische Weg bestünde dann darin, eine Erweiterung in C zu schreiben. Es ist jedoch möglich, jede beliebige Sprache zu verwenden, sofern diese über eine Wrapper-Bibliothek für Python verfügt.

Argumente für Rust

Als Erweiterung stünde insbesondere Rust zur Verfügung. Rust ist eine innovative kompilierte Sprache mit Schwerpunkt auf Sicherheit, die bereits unter Entwicklern einer großen Beliebtheit erfreut. Selbst das Erlernen von Rust bietet eine großartige Möglichkeit für Python-Developer, ihre Programmierkenntnisse zu verbessern.

Entscheidend jedoch ist, dass die Sprache Rust fast keine Laufzeit aufweist, wodurch sie zu einer dynamischen Bibliothek gut passt. Schließlich möchte niemand eine andere komplexe Laufzeit im selben Prozess wie den Python-Interpreter. Denn dies könnte zu vielen kniffligen Problemen führen.

Allerdings muss man mit Rust eine etwas steile Lernkurve durchlaufen. Programmierende könnten darüber nachdenken, ihre Codebasis aufzuteilen und kritischen Code in Rust und häufigeren Code, beispielsweise einen Webdienst, in Python zu schreiben.

Kombinationen aus Python und Rust

PyO3 ermöglicht es, das Beste aus beiden Welten zu nutzen, indem beispielsweise Python-Erweiterungen in Rust realisierbar sind. Das heißt, mit PyO3 schreiben Entwickler Rust-Code, geben an, wie er mit Python interagiert, kompilieren dann Rust und stellen dies direkt in einer virtuellen Python-Umgebung bereit, wo sie es mit dem Python-Code verwenden können.

Wenn Entwickler Rust mit Python oder Python mit Rust verwenden möchten, müssten sie sich jedoch vorübergehend mit beiden Sprachen vertraut machen, um die besten Ergebnisse zu erzielen. Sie müssten sich auch entscheiden, welche der beiden ihre Hauptsprache sein soll, da die Optionen für jeden Ansatz erheblich unterschiedlich sind.

Variante: Python mit Rust

Wenn Python als Hauptsprache erwählt wurde, funktioniert die Integration mit Rust konzeptionell genauso wie die Integration von Python mit C. Die in C geschriebene Standard-Implementierung von Python verwendet Erweiterungen, die entweder in C geschrieben sind oder ein C-kompatibles Application Binary Interface (ABI) verwenden.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

In Rust geschriebene Erweiterungen, die dieselbe ABI verwenden, funktionieren ebenfalls, obwohl dies nicht automatisch geschieht. Es müssen Crates verwendet werden, die dafür entwickelt wurden, um Bindungen für Rust-Funktionen an die Python-C-API bereitzustellen.

Die bekannteste Möglichkeit, um Rust-Bindungen in Python zu erstellen, ist PyO3. Es kann zum Schreiben von Python-Modulen in Rust oder zur Integration der Python-Laufzeitumgebung in eine Rust-Binärdatei verwendet werden. PyO3 nutzt das Tool Maturin, das zum Erstellen von Rust-Crates mit Python-Paketen und -Bindungen dient.

Bei der Installation in einer virtuellen Python-Umgebung lässt sich Maturin über die Befehlszeile nutzen, um ein neues Rust-Projekt mit aktivierten Python-Bindungen zu initialisieren. Entwickler verwenden Anweisungen im Rust-Code, um anzugeben, welche Rust-Funktionen für Python verfügbar gemacht werden sollen und wie das gesamte Rust-Projekt für Python als importierbares Modul bereitgestellt werden kann.

Variante: Rust mit Python

Wenn Entwicklerinnen und Entwickler hauptsächlich mit Rust arbeiten, aber Python in einer Rust-Anwendung verwenden möchten, ist die Cpython-Crate eine einfache Möglichkeit, dies zu bewerkstelligen. Die Cpython-Crate stellt Rust-Anbindungen an den CPython-Interpreter bereit, der die gebräuchlichste Python-Laufzeitumgebung ist. Rust-Programme können den CPython-Interpreter aufrufen und damit arbeiten, sodass sich Python-Objekte in Rust erstellen bzw. verändern und Bibliotheksaufrufe durchführen lassen.

Die Cpython-Crate enthält auch ein paar nützliche Makros. Das py_fn!Makro umschließt beispielsweise eine Rust-Funktion, sodass sie von Python aus aufgerufen werden kann. Mit dem py_class!Makro können Entwickler Rust-Klassen als Python-Klassenobjekte generieren. Wenn Entwickler mit Rust besser vertraut sind als mit Python, ist es angezeigt, sich zumindest vorübergehend mit der Python-C-API und den verschiedenen Python-Objekttypen vertraut zu machen.

Ein wichtiger Vorbehalt sowohl bei CpythonPyO3 als auch bei PyO3 besteht darin, das Hin- und Herschieben von Daten zwischen den beiden Sprachen möglichst zu minimieren. Jeder Aufruf von Python nach Rust oder umgekehrt verursacht etwas Overhead. Wenn der Overhead die Arbeit in Rust überwiegt, wird keine signifikante Leistungsverbesserung festzustellen sein.

(ID:49709133)