adesso Blog

In diesem Blog-Beitrag möchte ich euch unsere Best Practices für die Python-Entwicklung vorstellen. Python, als eine der meistgenutzten Programmiersprachen weltweit, bietet eine Vielzahl von Möglichkeiten, um Lösungen auf professionelle und effiziente Weise zu implementieren. Aber um das Potenzial von Python voll auszuschöpfen, ist es entscheidend, die Best Practices zu verstehen und anzuwenden. Best Practices sind bewährte Verfahren, die sich als besonders effektiv und produktiv in der Softwareentwicklung erwiesen haben. Sie dienen als Leitfaden, um den Code lesbar, wartbar und performant zu halten. Sie helfen uns nicht nur dabei, Fehler zu vermeiden, sondern fördern auch eine konsistente und qualitativ hochwertige Codebasis.

Typisierung

Python ist eine dynamisch typisierte Sprache, was bedeutet, dass der Typ einer Variablen zur Laufzeit bestimmt wird. Obwohl dies Flexibilität und Benutzerfreundlichkeit bietet, kann es auch zu Fehlern führen, die schwer zu debuggen sind. Glücklicherweise bietet Python auch Annotationen für statische Typen durch Typen-Hinweise (engl. type hints). Im Folgenden werden wir die Typisierung in Python und die besten Praktiken diskutieren.

Typen-Hinweise wurden in Python 3.5 mit PEP 484 eingeführt und sind eine Möglichkeit, den erwarteten Typ einer Variablen oder den Rückgabewert einer Funktion anzugeben.

	
	def add(a, b):
	                return a + b
	def add(a: int, b: int) -> int:
	                return a + b
	

In dem obigen Beispiel zeigen die „: int“-Teile an, dass die Funktion add erwartet, dass a und b vom Typ int sind. Der „-> int“ zeigt an, dass die Funktion add einen int zurückgibt.

Typen-Hinweise sind optional in Python und ihr Gebrauch hängt von dem spezifischen Anwendungsfall und dem Entwicklerteam ab. Hier sind einige Gründe, warum sie unbedingt verwendet werden sollten:

  • 1. Lesbarkeit und Wartbarkeit: Typen-Hinweise machen den Code expliziter und leichter zu verstehen. Sie können besonders hilfreich sein, wenn der Code von anderen gelesen oder in Zukunft gewartet wird.
  • 2. Fehlervermeidung: Statische Typüberprüfung kann einige Fehler aufdecken, bevor der Code ausgeführt wird. Tools wie Mypy können verwendet werden, um Tippfehler im Python-Code zu finden.
  • 3. Bessere IDE-Integration: Viele moderne Entwicklungsumgebungen können Typen-Hinweise verwenden, um bessere Autovervollständigung und Refactoring-Tools anzubieten.

Das Hinzufügen von Typen-Hinweisen beeinträchtigt nicht die Art und Weise, wie das Programm sonst laufen würde. Typen-Hinweise sind eine Art Kommentar. Der Code kann auch ausgeführt werden, wenn diese nicht beachtet oder falsch verwendet werden.

Mypy

Mypy stellt einen hochgradig ausgereiften statischen Typisierungsprüfer für die Programmiersprache Python dar, dessen Hauptzweck in der Sicherstellung der Integrität und der Genauigkeit des Quellcodes besteht. Dieses ausgeklügelte Softwarewerkzeug überprüft die Typkonformität eines Python-Programms, basierend auf Typen-Anmerkungen gemäß den Vorgaben des Python Enhancement Proposal (PEP) 484. Es erzeugt Warnmeldungen, wenn Typen nicht korrekt verwendet werden.

In Anbetracht der Tatsache, dass Python eine dynamische Sprache ist, treten typische Fehler oftmals erst während der Laufzeit auf. Mypy jedoch, als statischer Typisierungsprüfer, zeichnet sich dadurch aus, dass es in der Lage ist, solche Fehler zu identifizieren, ohne dass der betreffende Code effektiv ausgeführt werden muss. Diese Fähigkeit ermöglicht eine frühzeitige Fehlererkennung und trägt wesentlich zur Verbesserung der Qualität des Endprodukts bei, indem sie dazu beiträgt, eine robuste und fehlerfreie Codebasis zu gewährleisten.

Hier ist ein kleines Beispiel:

	
	number = input(“What is your favorite number?”)
	Print(“It is”, number +1) # error: Unsupported operand types for + (“str” and “int)
	

Mypy stellt ein ausgeklügeltes und intuitiv bedienbares Typsystem zur Verfügung, das eine breite Palette an Funktionen unterstützt. Diese umfassen Typinferenz, Generics, aufrufbare Typen, Tupeltypen, Union-Typen und strukturelle Subtypisierung, um nur einige zu nennen. Solche Funktionen tragen maßgeblich zur Sicherstellung einer erhöhten Typsicherheit und Konsistenz innerhalb von Python-Programmen bei.

Die Integration von Mypy in den Softwareentwicklungsprozess kann einen signifikanten Beitrag zur Verbesserung der Code-Lesbarkeit und -Verständlichkeit leisten. Es kann ferner dazu beitragen, die Debugging-Prozesse zu vereinfachen und die Pflegeaufwände zu reduzieren. Mypy ermöglicht es, Typfehler bereits in einem frühen Stadium des Entwicklungszyklus zu identifizieren und zu korrigieren. Dies trägt wesentlich dazu bei, die Qualität der Software zu verbessern und die Produktivität der Entwicklerinnen und Entwickler zu optimieren.

Pydantic

Pydantic ist eine äußerst leistungsfähige Datenvalidierungs- und Einstellungsverwaltungsbibliothek, die sich auf die Verwendung von Typen-Hinweisen in Python stützt, um die Konvertierung von Daten zwischen komplexen Typen und Python-Standardtypen zu erleichtern. Diese Bibliothek bietet einen systematischen Ansatz für die Datenvalidierung und die Serialisierung beziehungsweise Deserialisierung, was dazu beiträgt, die Konsistenz und Integrität der Daten in verschiedenen Anwendungsfällen zu gewährleisten.

Die grundlegende Funktionalität von Pydantic besteht darin, Datenvalidierungsprozesse zu vereinfachen und zu straffen. Es stellt sicher, dass die eingegebenen Daten bestimmte vordefinierte Kriterien erfüllen, bevor sie weiterverarbeitet werden. Auf diese Weise kann Pydantic dabei helfen, Fehler und Inkonsistenzen bei der Datenverarbeitung frühzeitig zu erkennen und zu beheben.

Darüber hinaus nutzt Pydantic die Typen-Hinweise von Python, um die Konvertierung von Daten zwischen komplexen Typen und Python-Standardtypen zu erleichtern. Dies ermöglicht es den Entwicklerinnen und Entwicklern, komplizierte Datenstrukturen einfach und effizient zu manipulieren und zu verarbeiten.

Zusätzlich zur Datenvalidierung und Typkonvertierung bietet Pydantic auch Funktionen zur Serialisierung und Deserialisierung von Daten. Dies ermöglicht die einfache Umwandlung von komplexen Datenstrukturen in standardisierte Formate, die zum Speichern oder Übertragen von Daten verwendet werden können, und umgekehrt. Insgesamt bietet Pydantic eine robuste und zuverlässige Lösung für die Datenverwaltung in Python-basierten Anwendungen. Es verbessert die Qualität des Codes, erhöht die Effizienz der Datenverarbeitung und trägt zur Gesamtstabilität und Zuverlässigkeit der entwickelten Software bei.

Code-Formatierung

Die Einhaltung eines bestimmten Code-Formatierungsstils ist ein entscheidendes Element der Softwareentwicklung. Es trägt nicht nur zur Verbesserung der Lesbarkeit und Verständlichkeit des Codes bei, sondern erhöht auch die Wartbarkeit und die langfristige Pflege des Projekts. Dies ist besonders wichtig, wenn an einem Projekt mehrere Personen beteiligt sind, um sicherzustellen, dass alle auf konsistente und einheitliche Weise arbeiten. Ohne eine solche Einigkeit kann das Arbeiten mit Versionskontrollsystemen wie Git und automatischen Formatierungstools zu komplexen und schwer zu lösenden Merge-Konflikten führen. Der PEP 8 – ein Style Guide für Python – bietet eine solide Grundlage für die Einhaltung eines kohärenten Code-Stils. Er definiert eine Reihe von Konventionen und Praktiken, die dazu beitragen, den Code organisiert, sauber und effizient zu halten.

Die Beachtung dieser Leitlinien kann dazu beitragen, die Qualität des Codes zu verbessern und eine konsistente Codebasis innerhalb des Teams zu fördern. Zusätzlich zur Verwendung von Style Guides können automatische Formatierungstools wie autopep8 oder black dazu beitragen, die Einhaltung des Stils zu erleichtern. Diese Tools können so konfiguriert werden, dass sie den vorgegebenen Stil automatisch auf den gesamten Code anwenden. Dies stellt sicher, dass alle Entwicklerinnen und Entwickler denselben Formatierungsstandard befolgen, unabhängig von ihren individuellen Vorlieben oder Gewohnheiten. Die meisten modernen integrierten Entwicklungsumgebungen (IDEs) bieten die Möglichkeit, diese Formatierungstools direkt zu integrieren. Dies ermöglicht eine nahtlose und effiziente Formatierung des Codes während des gesamten Entwicklungsprozesses. Auf diese Weise können Entwicklerinnen und Entwickler sich auf das Schreiben eines qualitativ hochwertigen Codes konzentrieren, während sie sich darauf verlassen können, dass die Einheitlichkeit und Konsistenz des Codes durch die automatische Formatierung gewährleistet wird. Es ist absolut empfehlenswert, die Code-Formatierung durch ein Pre-commit-Script zu gewährleisten.

Ruff

Ruff stellt eine bedeutende Weiterentwicklung in der Landschaft der Python-Linter dar. Linter sind essenzielle Werkzeuge in der Softwareentwicklung, da sie den Code auf mögliche Fehler, Sicherheitsrisiken und unerwünschte Praktiken analysieren. Sie spielen eine Schlüsselrolle bei der Aufrechterhaltung der Codequalität und fördern die Einhaltung von Best Practices in der Programmierung. In der Python-Community gibt es eine Vielzahl von Linting-Optionen, darunter renommierte Tools wie Pylint, Flake8 und Autoflake. Ruff zeichnet sich jedoch durch seine überlegene Geschwindigkeit, den Umfang seiner Analysen und seine hohe Kompatibilität mit anderen Werkzeugen, wie zum Beispiel dem Code-Formatierer black, aus. Es wurde in der Hochleistungssprache Rust entwickelt, was zu einer bemerkenswerten Leistungssteigerung führt. Tatsächlich ist Ruff 10 bis 100 Mal schneller als viele vergleichbare Programme, was eine effiziente und reibungslose Entwicklungsarbeit ermöglicht.

Darüber hinaus bietet Ruff über 700 integrierte Regeln für die Code-Analyse, eine beeindruckende Anzahl, die die Breite und Tiefe seiner Prüfungen demonstriert. Diese Regeln decken eine weite Palette von Best Practices und potenziellen Fehlerquellen ab und liefern wertvolle Rückmeldungen und Verbesserungsvorschläge für Entwicklerinnen und Entwickler.

Die meisten modernen integrierten Entwicklungsumgebungen bieten die Möglichkeit, Ruff direkt zu integrieren und zu verwenden. Dadurch wird es zu einem nahtlosen Teil des Entwicklungsworkflows, der die Codequalität ständig überwacht und zur Optimierung des Codes beiträgt. Insgesamt ist Ruff ein außerordentlich leistungsfähiges Linter-Tool, das eine wichtige Rolle bei der Verbesserung der Codequalität und der Förderung effizienter und sicherer Programmierpraktiken in Python spielt. Auch Ruff kann man sehr gut in ein Pre-commit-Script integrieren.

Projektstruktur

Es ist wichtig, eine geordnete Projektstruktur zu haben, damit man alles sofort wiederfinden kann. Diese beinhaltet klassisch im Hauptordner die Dateien Readme, requirements.txt und Lizenz, je nach Projekt kommen noch pyproject.toml, setup.py und weitere hinzu. Als Ordner gibt es in der Regel „config“ für Konfigurationen, „docs“ für die Doku (etwa Sphinx), „tests“ für die Unit- und Integrationstests und einen Ordner mit dem Projektnamen, in den der eigentliche Code kommt. Die Struktur in Letzterem hängt sehr von der Art des Projektes ab (REST-Service, CLI-Tool, Monolith, Bibliothek etc.).

Die beschriebene Struktur ist das sogenannte „Flat-Layout“. Es gibt auch noch ein „src-Layout“, das meiner Meinung nach aber nur wenige Vorteile hat und auf das wir daher hier nicht genauer eingehen. Weitere Informationen und einen Vergleich der beiden Layouts gibt es hier: https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/

Ausblick

Im nächsten Blog-Beitrag werde ich ausführlich auf bewährte Praktiken im Bereich KI und Datenengineering eingehen. Wir werden tiefer in Themen wie Datenbereinigung, Modelltraining und Skalierung von KI-Systemen eintauchen. Es bleibt also spannend.

Bild Marc Mezger

Autor Marc Mezger

Marc Fabian Mezger ist AI Specialist Consultant, der sich auf die Bereiche Medical Deep Learning, Computer Vision und Drift spezialisiert hat. In seiner aktuellen Rolle im Competence Center AI & Data Science ist er für die Beratung von Kunden zu AI-Lösungen und deren Umsetzung verantwortlich. Er verfügt über umfangreiche Kenntnisse im Bereich Machine und Deep Learning.

Bild Moritz Momper

Autor Moritz Momper

Moritz ist Data Engineer bei adesso. Er hat sich auf Python-basierte Data Engineering und Backend-Entwicklung in Go spezialisiert, um innovative Lösungen für Datenverarbeitung und -analyse zu schaffen.

Diese Seite speichern. Diese Seite entfernen.