[Übersetzung] Python statischer Typ, erstaunlicher Mypy!

Dieser Artikel ist eine Übersetzung eines Artikels von Tim Abbott am Donnerstag, den 13. Oktober 2016.

Haftungsausschluss

Dieser Artikel ist ein ** inoffizieller ** übersetzter Artikel (wir haben bestätigt, dass die Übersetzung für den Autor Tim Abbott veröffentlicht wird). Tim Abbott und Dropbox übernehmen keine Verantwortung für den Inhalt dieses Artikels.

Wenn Sie falsche Übersetzungen haben, senden Sie mir bitte eine Bearbeitungsanfrage.

Vielen Dank

Vielen Dank für die Verbesserung meiner schlechten Übersetzung!

Python statischer Typ, erstaunlicher Mypy!

  1. Oktober 2016

— Tim Abbott

In den letzten Jahren wurden statische Prüfer in PHP (Hack) und JavaScript (Flow und [TypeScript](https: /) verwendet. Es ist in populären dynamisch typisierten Sprachen wie /www.typescriptlang.org/)) verfügbar und wird immer häufiger eingesetzt. Vor zwei Jahren wurde Python 3 Temporäre Syntax für statische Typanmerkungen hinzugefügt. Statische Typen in Python sind jedoch noch nicht weit verbreitet. Der Grund dafür ist, dass das Tool zur Überprüfung von Typanmerkungen mypy nicht von einer Qualität war, die in der Produktion verwendet werden konnte. Aber das ist die Geschichte bis jetzt!

Es gibt einige interessante Neuigkeiten im letzten Jahr. Ein Team von Dropbox (einschließlich Guido van Rossum, dem Schöpfer von Python!) Hat an mypy gearbeitet, um gut als Typprüfung zu funktionieren, die Python-Programmen statische Typintegrität verleiht. Für viele Entwickler mit großen Python 2-Codebasen gibt es noch interessantere Neuigkeiten. mypy unterstützt auch die Überprüfung des Python 2-Programmtyps vollständig, kann große Python-Codebasen unterstützen und die Verwendung von mypy vereinfacht das Upgrade auf Python 3 erheblich.

Während des gesamten Jahres 2016 hat die Zulip-Entwicklergemeinde diese Vorteile für mypy gesehen. Zulip ist eine beliebte Open-Source-Gruppenchat-Anwendung. Es verfügt über Apps für alle wichtigen Plattformen, REST-APIs und viele Erweiterungstools. Zulip ist ein Produkt in Python 2 mit etwa 50.000 Zeilen und Hunderten von Commits von Dutzenden von Entwicklern pro Monat. Während des gesamten Jahres 2016 haben wir 100% statische Typanmerkungen mit mypy im Backend (!). Und dank mypy bin ich gerade dabei, auf Python 3 umzusteigen. Zulip ist jetzt das größte Open-Source-Python-Projekt mit vollständig statischen Typen. Ich bin jedoch skeptisch, ob ich diesen Titel in Zukunft noch lange behalten kann :)

In diesem Artikel werde ich erklären, wie mypy funktioniert, welche Vorteile und Schmerzen wir mit mypy erlebt haben. Und teilen Sie eine detaillierte Anleitung zur Einführung von mypy für große Codebasen in der Produktion (Finden und Beheben von Dutzenden von Herausforderungen für große Projekte, die in den ersten Tagen nach der Verwendung von mypy auftreten. Einschließlich Methoden!).

Eine kurze Einführung in mypy

Hier ist ein kurzes Beispiel für die Annotationssyntax für mypy / PEP-484 in Python 3.

def sum_and_stringify(nums: List[int]) -> str:  
    """Adds up the numbers in a list and returns the result as a string."""
    return str(sum(nums))

Und ich zeige Ihnen, wie derselbe Code mit der in Python 2 und 3 verfügbaren Kommentarsyntax aussieht.

def sum_and_stringify(nums):  
    # type: (List[int]) -> str
    """Adds up the numbers in a list and returns the result as a string."""
    return str(sum(nums))

Mit dieser Kommentarsyntax unterstützt mypy die regelmäßige Überprüfung des Python 2-Programmtyps. Mit mypy annotierte Programme werden in jeder Python-Ausführungsumgebung normal ausgeführt (diese großartige Eigenschaft von mypy ist auch im JavaScript-Prüfer Flow üblich). Das ist großartig. Dies bedeutet, dass Sie mypy für Ihr Projekt übernehmen können, ohne die Ausführung von Python zu ändern.

Wenn Sie mypy like linter ausführen, wird ein Fehler in einem ausgeklügelten Compiler-Format ausgegeben. Wenn Sie beispielsweise fälschlicherweise kommentieren, dass "sum_and_stringify" einen Gleitkommawert zurückgibt, gibt mypy eine Ausgabe ähnlich der folgenden zurück:

$ mypy /tmp/test.py
/tmp/test.py: note: In function "sum_and_stringify":
/tmp/test.py:6: error: Incompatible return value type: expected builtins.float, got builtins.str

Wenn Sie daran interessiert sind, wie Sie mypy syntax cheat sheet (einfache Verwendung) und [PEP-484](https: // Besuchen Sie www.python.org/dev/peps/pep-0484/) (für komplexe Anwendungen). Das sind großartige Dokumente. Wenn Sie mypy jetzt ausprobieren möchten, können Sie es mit pip3 install mypy-lang installieren.

Wenn mypy auch vollständige Typanmerkungen für Module und deren abhängige Pakete enthält, erhalten Sie eine sehr leistungsstarke Funktion zur Konsistenzprüfung. Es ähnelt dem, was der Compiler in einer statisch typisierten Sprache erhält. mypy verwendet typeshed, ein Repository vom Typ "stub" (stub: Typdefinition des Moduls des Header-Dateistils), der Python-Standardbibliothek, Anforderungen, sechs und Es bietet Typinformationen für Dutzende beliebter Bibliotheken wie sqlalchemy. Wichtig ist, dass mypy so konzipiert ist, dass nach und nach Typen hinzugefügt werden. Wenn die Typinformationen des importierten nicht verfügbar sind, werden sie einfach als mit einem beliebigen Typ konsistent behandelt.

Vorteile der Verwendung von mypy

Hier sind einige der Vorteile, die wir mit mypy gefunden haben. Wir werden die wichtigsten in der richtigen Reihenfolge abholen.

Was war schmerzhaft

Ich denke, es ist auch wichtig, über die Schmerzen bei der heutigen Verwendung von Mypy zu sprechen, um ein vollständiges Bild der Erfahrung bei der Einführung von Mypy zu erhalten.

Es war kein Schmerz

In diesem Abschnitt mache ich mir Sorgen, dass es ein Problem sein könnte (bevor ich mypy ausprobiere), aber ich werde nach der Einführung von mypy zurückblicken und überlegen, was ich nicht für ein großes Problem halte.

Finde in den ersten Tagen Fehler in mypy

In diesem Abschnitt erfahren Sie, was Sie tun müssen, um von mypy in einer großen Codebasis profitieren zu können. Um Ihnen einen Eindruck vom Umfang der erforderlichen Arbeit zu geben, schrieb dieser Abschnitt alles auf, was ich während des viertägigen Hackathons im Januar getan habe (obwohl mypy zu dieser Zeit noch nicht ausgereift war, verbrachte ich die Hälfte meiner Zeit selbst. Ich habe einen entsprechenden Fehlerbericht für den gefundenen Fehler geschrieben. Wenn Sie die Verwendung von mypy in Betracht ziehen, aber weitere Informationen benötigen, um diese Entscheidung zu treffen, empfehle ich Ihnen, alle in diesem Abschnitt beschriebenen Schritte auszuführen. Die Mühe, die Sie bezahlt haben, ist es wert.

** Lies mypy Spickzettel. ** Der mypy-Spickzettel (http://mypy.readthedocs.io/en/latest/cheat_sheet.html) bietet einen klaren Überblick über die PEP-484-Syntax. Und Sie werden häufig darauf verweisen, wenn Sie mit dem Schreiben von Typanmerkungen beginnen.

** Standardisieren Sie, wie mypy ausgeführt wird. ** Installieren Sie mypy (https://github.com/zulip/zulip/blob/master/tools/install-mypy) auf Ihrer Codebasis und führen Sie es aus (https: // github.com/zulip/zulip/blob/master/tools/run-mypy) Erstellen Sie ein Tool, um dies zu tun. Stellen Sie sicher, dass alle Mitglieder des Projekts die Typprüfung auf dieselbe Weise ausführen können. Zwei Funktionen sind wichtig, um mypy auszuführen.

Vermeiden Sie Fehler, wenn Sie mypy auf Ihrer Codebasis ausführen. Normalerweise müssen Sie der globalen leeren Datenstruktur Typanmerkungen hinzufügen. Ungefähr im Januar dauerte dieser Vorgang 2-3 Stunden (einschließlich der Zeit, um einen Fehler zu melden, der schrieb, wie er reproduziert werden soll). Wahrscheinlich jetzt viel weniger Arbeitszeit. Standardmäßig prüft mypy nur kommentierte Funktionen. Aus diesem Grund können Sie mit nicht kommentierten Codebasen zunächst die gesamte mypy-Codebasis analysieren.

** Überprüfen Sie die grundlegende Integrität. ** Fügen Sie dem Argument von mypy --check-untyped-defs hinzu. Und stellen Sie sicher, dass Sie keinen Fehler erhalten, wenn Sie mypy auf dieser Codebasis ausführen. Diese Option veranlasst mypy, alle defs in der Codebasis auf interne Integrität zu überprüfen. Mit anderen Worten, mypy erkennt viele Fehler und Fehler in der Codebasis, selbst wenn keine Typanmerkungen geschrieben sind.

In vielen Fällen möchten Sie Fehler und schrecklichen Code beheben, aber Sie können auch die Annotation "# type: ignore" verwenden oder Dateien ausschließen, um das Problem zu verschieben. Zum Beispiel haben wir zuerst alle Zulip-Tests ausgeschlossen. Das liegt daran, dass es sich nicht lohnt zu tippen und es gab viele Affen-Patches und verdächtige Python-Skripte. In Zulip habe ich ungefähr zwei Tage lang hart gearbeitet, um den Fehler aus der Ausgabe von "--check-untyped-defs" zu beseitigen, und in Zulips Codebasis zusammengeführt, um ungefähr 40 Probleme zu beheben.

Ich verbrachte noch ein oder zwei Tage damit, einen guten Weg zu finden, um den aufgetretenen Mypy-Fehler zu reproduzieren und die Typisierung zu verbessern. Mypy befindet sich nicht mehr in seiner anfänglichen Entwicklung und es kommt seltener vor, dass Bugs in mypy auftreten. Bei großen Projekten sollten Sie jedoch mit Fehlern rechnen und die typisierten Fehler beheben (senden Sie einfach eine PR!).

** Führen Sie mypy mit kontinuierlicher Integration aus. ** Sobald Ihre Codebasis "mypy --check-untyped-defs" besteht, empfiehlt es sich, in Ihrer CI-Umgebung eine Typprüfung für "mypy" durchzuführen, um Ihren Fortschritt abzuschließen.

Die Typanmerkung von mypy ist optional. Nachdem Sie die oben beschriebenen Einrichtungsschritte ausgeführt haben, können Sie Ihre Codebasis in Ihrem eigenen Tempo mit Anmerkungen versehen. Mit der Zeit werden Sie von statischen Typen in den mit Anmerkungen versehenen Teilen Ihrer Codebasis profitieren. Sie müssen für den Rest der Codebasis nichts Besonderes tun (das Wunder der progressiven Eingabe!). Im nächsten Abschnitt werden Strategien beschrieben, mit denen Sie Ihre Codebasis vollständig mit Anmerkungen versehen können.

Kommentieren Sie große Codebasen vollständig

In diesem Abschnitt sehen wir uns an, wie Sie ab dem Zeitpunkt, an dem Sie mypy eingerichtet haben, Typanmerkungen in Ihrer Codebasis abrufen können.

Das Tolle an mypy ist, dass Sie die ganze Arbeit schrittweise erledigen können. Nach der Ersteinrichtung haben wir 2-3 Monate lang nichts getan. Die Änderung erfolgte, als wir die Typanmerkung von mypy als eines unserer Google Summer of Code (GSOC) -Projekte vorstellten. In diesem Projekt haben wir einen wunderbaren Studenten namens Eklavya Sharma getroffen. Eklavya hat die meiste harte Arbeit geleistet, um Zulip zu kommentieren. Er hat unsere Tools aktualisiert, die Kernbibliothek mit Anmerkungen versehen, Fehlerberichte und PR in den Upstream von mypy und typeshed eingebracht und alle Fehler behoben, die wir in den frühen Tagen gemacht haben. tat. Überraschenderweise hat er Zulip in diesem Sommer auch auf virtualenv migriert und Zulip auf Python 3 aktualisiert!

Die Annotation eines großen Projekts kann in mehrere Phasen unterteilt werden.

** Phase 1: Kommentieren Sie die Kernbibliothek. ** Strategisch möchten Sie zuerst den Code in den Kernbibliotheken kommentieren, die überall in anderen Dateien verwendet werden. Typanmerkungen für diese Funktionen beschränken die an anderer Stelle im Code verwendeten Typen. Wenn Sie zuerst an diesen Dateien arbeiten, verbringen Sie weniger Zeit damit, falsche Anmerkungen zu beheben und echte Fehler schneller zu erkennen. Darüber hinaus wird in dieser Phase eine Dokumentation über wie das Projekt mypy verwendet (und über den Ausfall von mypy im CI-System) geschrieben. (Link zur Dokumentation) Es ist auch eine gute Gelegenheit.

** Phase 2: Kommentieren Sie den größten Teil der Codebasis. ** Bei vielen Projekten wird es wahrscheinlich Monate dauern, bis Entwickler langsam an verschiedenen Teilen der Codebasis arbeiten. Es ist eine sehr rationale Strategie.

Es funktioniert auch gut, sich auf das Kommentieren der Codebasis zu konzentrieren. Es wäre hilfreich darüber zu sprechen, wie Zulip diese Arbeit gemacht hat. Fast die Hälfte von Eklavyas Code-Sommer wollten wir Zulip so weit wie möglich kommentieren, und wir PyCon Sprint. ). PyCon Sprint ist meine Lieblingsveranstaltung bei PyCon. Es ist die beste viertägige Rallye nach der zentralen PyCon-Konferenz. Dort arbeiten Hunderte von Entwicklern gemeinsam an Open Source-Projekten. Es ist eine großartige Gelegenheit, völlig frei zu sein, um an Open Source-Projekten teilzunehmen und Beiträge zu leisten.

Wir haben eine Tabelle neben mypy-Entwicklern reserviert und uns darauf eingestellt, jeden Tag 5-10 Entwickler in Zulips mypy-Annotationsprojekt zu ziehen. Während des PyCon-Sprints stieg der Prozentsatz der mit Anmerkungen versehenen Zulip von 17% auf 85% (25 bis 30 Ingenieure arbeiten täglich, von denen die meisten sowohl in Zulip als auch in Mypy unerfahren sind. tat). Wir haben mypy's Coverage Support und coveralls.io verwendet, um unseren Fortschritt zu verfolgen, aber der Fortschrittsbalken auf einem großen Blatt Papier ist interessanter. Dies wurde am Anfang des letzten Tages aufgenommen.

Zulip mypyカバレッジゴール

Ich denke, unsere Erfahrung mit PyCon hat eindeutig gezeigt, dass es einfach ist, mit neuen Entwicklern mit mypy zu arbeiten. Mit Ausnahme von mir waren alle Mitwirkenden, die Anmerkungen hinzugefügt haben, sowohl mit Zulip als auch mit mypy unerfahren. Mit der richtigen 5-minütigen Demo und einer guten Dokumentation haben wir festgestellt, dass neue Mitwirkende innerhalb einer Stunde nach dem Beginn der Berührung mit mypy effizient arbeiten. Ich empfehle diesen mypy hackason Ansatz zuversichtlich für andere Open Source Projekte. Dieser großartige Ansatz kann erhebliche Auswirkungen auf die Mitwirkenden haben, selbst auf unbekannte Projekte.

** Phase 3: 100%. ** Das Kommentieren der letzten Dateien ist schwieriger als zuvor. Der Grund ist, dass diese Phase alle Fehler debuggt, die Sie in Phase 2 gemacht haben. Dabei ist es wichtig, bis zu 100% der Dateien und Verzeichnisse zu bereinigen. Aus diesem Grund verfügt das Flag "mypy" über die Option "--disallow-untyped-defs" (mit Typanmerkungen). Vermeiden wir eine Regression durch Hinzufügen (Berichtsfunktionen, die nicht vorhanden sind).

Eklavya machte es 85% bis 96%, bevor die Universität wiedereröffnet wurde. Danach haben wir vor einigen Wochen 2-3 Stunden gearbeitet, um 100% zu erreichen. Der gesamte neue Python-Code, den ich Zulip hinzufüge, ist jetzt mit mypy versehen (allerdings mit einer reduzierten Anzahl, mit Ausnahme einiger Skripte, Einstellungen und Testdateien).

** Phase 4: Feiern und schreiben Sie einen Blog-Beitrag! ** Zumindest war dies der nächste Schritt für Zulip :)

Insgesamt waren es der einwöchige Hackathon, das GSOC-Projekt und das PyCon-Sprint-Treffen, die dazu führten, dass Zulip in Zeiten intensiver Arbeit vollständig kommentiert wurde. Dies ist natürlich eine triviale Anstrengung.

Ich muss sagen, dass Zulips Mypy-Reise noch nicht abgeschlossen ist, obwohl Zulip zu 100% kommentiert ist. Schließlich möchten wir typisierten Bibliotheken, die von Zulip verwendet werden (z. B. Django), einen Stub hinzufügen.

Empfehlungen zum Kommentieren von Code

Es gibt Empfehlungen, mit denen Sie beim eigentlichen Kommentieren Zeit sparen können.

bad_code # type: ignore # https://github.com/python/typeshed/issues/372

Mit dieser Methode können Sie leicht feststellen, ob Probleme, die in Zukunft mit "type: ignore" vermieden wurden, vorgelagert wurden. Wenn Sie einer Datei viele "type: ignore" -Anmerkungen hinzufügen müssen, können Sie diese zur Ausschlussliste hinzufügen (eine Funktion unseres "run-mypy" -Wrappers) und verschieben. ..

Fazit

Die Erfahrung mit mypy (und dem System vom Typ PEP-484) war durchweg großartig. Und wir sind der Meinung, dass die Einführung von mypy ein großer Fortschritt für das Zulip-Projekt ist. mypy verbessert die Lesbarkeit, fängt Fehler ab, ohne zu laufen, hat nur sehr wenige Fehlalarme und keine größeren Nachteile. Die Nutzung von mypy in einer großen Codebasis war eine relativ kleine Investition in unser Projekt. Darüber hinaus hat das Annotieren der Codebasis den sekundären Vorteil, dass der Übergang zu Python 3 erleichtert wird.

Wenn Sie eine große Python-Codebasis haben und Ihre Codebasis verbessern möchten, sollten Sie sich eine Woche Zeit nehmen, um mypy zu verwenden!

Wenn Sie neugierig sind, wie statische Python-Typen in einer großen Codebasis aussehen, lesen Sie das Zulip Server-Projekt auf GitHub (https://github.com/zulip/zulip/). .. Wir freuen uns über neue Mitwirkende!

Besonderer Dank geht an Guido van Rossum, Alya Abbott, Steve Howell, Jason Chen, Eklavya Sharma, Anurag Goel und Joshua Simmons für ihr Feedback zu diesem Blogbeitrag.

Tim Abbott

Tim Abbott ist der Hauptentwickler des Zulip Open Source-Projekts. Er war CTO von Ksplice (bevor er von Dropbox übernommen wurde) und später von Zulip.

San Francisco https://zulip.org

Recommended Posts

[Übersetzung] Python statischer Typ, erstaunlicher Mypy!
Numerischer Python-Typ
Python2-Zeichenfolgentyp
Python # String-Typ
Statische Typprüfung, die in Python lose beginnt
[Übersetzung] 25 Jahre alter Python
Python # Überprüfen Sie die Typidentität
[Übersetzung] PEP 0484 --Tipps
Python --Überprüfen Sie den Wertetyp
Statische Analyse von Python-Programmen
Unveränderlicher Python-Typ int memo
Python-Datentyp-Zusammenfassungsnotiz
Konvertierung von Bilddatentypen [Python]