{"id":38649,"date":"2019-10-31T22:25:04","date_gmt":"2019-10-31T19:25:04","guid":{"rendered":"https:\/\/prohoster.info\/blog\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\/"},"modified":"2019-10-31T22:25:04","modified_gmt":"2019-10-31T19:25:04","slug":"put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Wir pr\u00e4sentieren Ihnen den dritten Teil unserer \u00dcbersetzung des Materials \u00fcber den Weg, den Dropbox bei der Implementierung eines Python-Code-Typpr\u00fcfsystems gegangen ist.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/757669265e870de604388c66adef814d.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>\u2192 Vorherige Teile: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">erster<\/a><\/noindex> und <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">zweiter<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Erreichung von 4 Millionen Zeilen typisiertem Code<\/h2>\n<p>\nEine weitere wichtige Aufgabe (dies war das zweith\u00e4ufigste Anliegen in den internen Umfragen) war die Steigerung des Anteils des Dropbox-Codes, der Typpr\u00fcfungen unterzogen wurde. Wir haben verschiedene Ans\u00e4tze ausprobiert, um dieses Ziel zu erreichen \u2013 von einem nat\u00fcrlichen Wachstum der typisierten Codebasis bis hin zur Fokussierung der mypy-Teammitglieder auf statische und dynamische automatisierte Typinferenz. Letztendlich entstand der Eindruck, dass es keine einfache gewinnbringende Strategie gibt, aber wir konnten ein schnelles Wachstum des annotierten Codes erreichen, indem wir mehrere Ans\u00e4tze kombiniert haben.<\/p>\n<p>Durch unsere gr\u00f6\u00dfte Python-Repository (mit Backend-Code) hat die Anzahl der annotierten Codezeilen fast 4 Millionen erreicht. Die Arbeiten zur statischen Typisierung des Codes wurden \u00fcber etwa drei Jahre durchgef\u00fchrt. Mypy unterst\u00fctzt jetzt verschiedene Arten von Berichten zur Typabdeckung, die die \u00dcberwachung des Fortschritts der Typisierung erleichtern. Insbesondere k\u00f6nnen wir Berichte \u00fcber Code mit Unsicherheiten in den Typen erstellen, wie z.B. die explizite Verwendung von Typen <code>Any<\/code> in Anmerkungen, die nicht \u00fcberpr\u00fcfbar sind, oder wie der Import von Drittanbieter-Bibliotheken, die keine Typannotationen enthalten. Im Rahmen des Projekts zur Verbesserung der Typ\u00fcberpr\u00fcfung bei Dropbox haben wir zur Verbesserung der Typdefinitionen (sog. Stub-Dateien) f\u00fcr einige beliebte Open-Source-Bibliotheken im zentralen Python-Repository beigetragen <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Wir haben neue M\u00f6glichkeiten des Typsystems implementiert (und in sp\u00e4teren PEPs standardisiert), die es erm\u00f6glichen, genauere Typen f\u00fcr bestimmte Python-Muster zu verwenden. Ein bemerkenswertes Beispiel daf\u00fcr ist <code>TypeDict<\/code>, der Typen f\u00fcr JSON-\u00e4hnliche W\u00f6rterb\u00fccher bereitstellt, die eine feste Menge von String-Schl\u00fcsseln haben, wobei jeder einen eigenen Typwert hat. Wir werden unser Typensystem weiter ausbauen. Wahrscheinlich wird unser n\u00e4chster Schritt die verbesserte Unterst\u00fctzung der Python-Funktionen f\u00fcr den Umgang mit Zahlen sein.<\/p>\n<p><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Anzahl der annotierten Codezeilen: Server<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Anzahl der annotierten Codezeilen: Client<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Gesamtanzahl der annotierten Codezeilen<\/i><\/p>\n<p>Hier ist eine \u00dcbersicht der wichtigsten Merkmale der Ma\u00dfnahmen, die wir zur Erh\u00f6hung der annotierten Codezeilen in Dropbox ergriffen haben:<\/p>\n<p>Strenge der Annotation. Wir haben die Anforderungen an die Strenge der Annotation neuen Codes schrittweise erh\u00f6ht. Wir begannen mit Linter-Empfehlungen, die vorschlugen, Annotationen in Dateien hinzuzuf\u00fcgen, die bereits einige Annotationen enthalten. Jetzt verlangen wir, dass Typannotationen in neuen Python-Dateien und in den meisten bestehenden Dateien vorhanden sind.<\/p>\n<p>Typisierungsberichte. Wir senden w\u00f6chentlich Berichte an die Teams \u00fcber den Typisierungsgrad ihres Codes und geben Ratschl\u00e4ge dazu, was zuerst annotiert werden sollte.<\/p>\n<p>F\u00f6rderung von mypy. Wir berichten \u00fcber mypy auf verschiedenen Veranstaltungen und stehen Teams zur Seite, um ihnen den Einstieg in die Typannotation zu erleichtern.<\/p>\n<p>Umfragen. Wir f\u00fchren regelm\u00e4\u00dfige Umfragen unter Nutzern durch, um die Hauptprobleme zu identifizieren. Wir sind bereit, weit zu gehen, um diese Herausforderungen anzugehen (sogar bis zur Schaffung einer neuen Sprache, um mypy zu beschleunigen!).<\/p>\n<p>Leistungsverbesserung. Wir haben die Leistung von mypy erheblich verbessert, indem wir einen Daemon und mypyc verwenden. Dies wurde getan, um die Unannehmlichkeiten w\u00e4hrend des Annotationprozesses zu gl\u00e4tten und um die Bearbeitung gro\u00dfer Codebasen zu erm\u00f6glichen.<\/p>\n<p>Integration mit Editoren. Wir haben Tools geschaffen, um die Ausf\u00fchrung von mypy in den bei Dropbox beliebten Editoren zu unterst\u00fctzen. Dazu geh\u00f6ren PyCharm, Vim und VS Code. Dies hat den Prozess der Annotation und der Funktionspr\u00fcfung von Code erheblich vereinfacht. Solche Ma\u00dfnahmen sind typischerweise beim Annotieren bestehender Codes erforderlich.<\/p>\n<p>Statische Analyse. Wir haben ein Tool zur Extraktion von Funktionssignaturen mithilfe statischer Analyse entwickelt. Dieses Tool funktioniert am besten in relativ einfachen Situationen, hat uns jedoch geholfen, den Codeumfang mit Typen m\u00fchelos zu erweitern.<\/p>\n<p>Unterst\u00fctzung von Drittanbieterbibliotheken. In vielen unserer Projekte verwenden wir das SQLAlchemy-Toolset. Es nutzt die dynamischen M\u00f6glichkeiten von Python, die von PEP 484-Typen nicht direkt modelliert werden k\u00f6nnen. In \u00dcbereinstimmung mit PEP 561 haben wir eine passende Stub-Datei erstellt und ein Plugin f\u00fcr mypy (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">Open Source<\/a><\/noindex>), das die Unterst\u00fctzung f\u00fcr SQLAlchemy verbessert.<\/p>\n<h2>Herausforderungen, mit denen wir konfrontiert wurden<\/h2>\n<p>\nDer Weg zu 4 Millionen Zeilen typisierten Codes war nicht immer leicht. Auf diesem Weg sind wir auf zahlreiche H\u00fcrden gesto\u00dfen und haben einige Fehler gemacht. Hier sind einige der Probleme, mit denen wir konfrontiert waren. Wir hoffen, dass dieser Bericht anderen hilft, \u00e4hnliche Probleme zu vermeiden.<\/p>\n<p>\u00dcbersehene Dateien. Wir haben mit der \u00dcberpr\u00fcfung nur einer kleinen Menge an Dateien begonnen. Alles, was nicht zu diesen Dateien geh\u00f6rte, wurde nicht \u00fcberpr\u00fcft. Dateien wurden zur Pr\u00fcfungslist hinzugef\u00fcgt, sobald die ersten Anmerkungen auftraten. Falls etwas aus einem Modul importiert wurde, das au\u00dferhalb des Pr\u00fcfbereichs lag, handelte es sich um die Arbeit mit Werten vom Typ <code>Any<\/code>, die \u00fcberhaupt nicht \u00fcberpr\u00fcft wurden. Dies f\u00fchrte zu einem erheblichen Verlust an Typgenauigkeit, insbesondere in den fr\u00fchen Phasen der Migration. Diese Methode funktionierte jedoch erstaunlich gut, obwohl es typischerweise der Fall war, dass das Hinzuf\u00fcgen von Dateien zur Typpr\u00fcfung Probleme in anderen Bereichen des Codes aufdeckte. Im schlimmsten Fall, wenn zwei isolierte Codeteile zusammengef\u00fchrt wurden, in denen die Typen unabh\u00e4ngig voneinander bereits \u00fcberpr\u00fcft worden waren, stellte sich heraus, dass die Typen dieser Bereiche nicht miteinander kompatibel waren. Dies f\u00fchrte zu einer Reihe von erforderlichen \u00c4nderungen in den Annotationen. Wenn wir nun zur\u00fcckblicken, erkennen wir, dass wir die grundlegenden Bibliotheksmodule fr\u00fchzeitig in den Typpr\u00fcfungsbereich von mypy aufnehmen sollten. Dies h\u00e4tte unsere Arbeit wesentlich planbarer gemacht.<\/p>\n<p>Annotation von altem Code. Als wir mit unserer Arbeit begannen, hatten wir etwa 4 Millionen Zeilen bereits bestehenden Python-Codes. Es war klar, dass die Annotation all dieses Codes keine leichte Aufgabe war. Daher entwickelten wir ein Werkzeug namens PyAnnotate, das zur Laufzeit w\u00e4hrend der Tests Typinformationen sammeln kann und in der Lage ist, Typspezifikationen basierend auf den gesammelten Informationen in den Code einzuf\u00fcgen. Allerdings haben wir keine umfassende Verbreitung dieses Werkzeugs festgestellt. Das Sammeln von Typinformationen war langsam, und die automatisch generierten Annotationen erforderten oft mehrere manuelle Anpassungen. Wir dachten dar\u00fcber nach, dieses Werkzeug bei jeder Code\u00fcberpr\u00fcfung automatisch auszuf\u00fchren oder Typinformationen basierend auf der Analyse einer bestimmten Menge echter Netzwerkaufrufe zu sammeln, entschieden uns jedoch dagegen, da jeder dieser Ans\u00e4tze zu riskant war.<\/p>\n<p>Zusammenfassend l\u00e4sst sich sagen, dass der Gro\u00dfteil des Codes manuell von seinen Eigent\u00fcmern annotiert wurde. Um diesen Prozess in die richtige Richtung zu lenken, erstellen wir Berichte \u00fcber besonders wichtige Module und Funktionen, die annotiert werden m\u00fcssen. So ist es beispielsweise wichtig, den bibliotheksmodul, der an vielen Stellen verwendet wird, mit Typannotations zu versehen. Im Gegensatz dazu ist es nicht mehr so wichtig, einen alten Dienst, der durch einen neuen ersetzt wird, zu annotieren. Dar\u00fcber hinaus experimentieren wir mit dem Einsatz statischer Analysen, um Typannotations f\u00fcr alten Code zu generieren.<\/p>\n<p>Zirkul\u00e4re Importe. Oben habe ich \u00fcber zirkul\u00e4re Importe (die \"Abh\u00e4ngigkeitskn\u00e4uel\") gesprochen, deren Existenz die Beschleunigung von mypy erschwerte. Zudem mussten wir intensiv daran arbeiten, mypy mit Unterst\u00fctzung f\u00fcr alle Arten von Idiomen auszustatten, die durch diese zirkul\u00e4ren Importe verursacht werden. K\u00fcrzlich haben wir ein umfassendes Redesign-Projekt abgeschlossen, das die meisten Probleme von mypy im Zusammenhang mit zirkul\u00e4ren Importen behoben hat. Diese Probleme stammen tats\u00e4chlich aus den sehr fr\u00fchen Tagen des Projekts, noch aus Alore, der Programmiersprache, auf die mypy urspr\u00fcnglich ausgerichtet war. Die Syntax von Alore erm\u00f6glicht es, Probleme mit zirkul\u00e4ren Importbefehlen leicht zu l\u00f6sen. Das moderne mypy hat einige Einschr\u00e4nkungen von seiner fr\u00fchen, einfachen Implementierung geerbt (die hervorragend f\u00fcr Alore geeignet war). Python macht die Arbeit mit zirkul\u00e4ren Importen haupts\u00e4chlich aufgrund der Mehrdeutigkeit von Ausdr\u00fccken komplizierter. Zum Beispiel kann w\u00e4hrend einer Zuweisungsoperation tats\u00e4chlich ein Typalias definiert werden. Mypy ist nicht immer in der Lage, solche Dinge zu erkennen, bis ein gro\u00dfer Teil des Importzyklus verarbeitet wurde. In Alore gab es solche Mehrdeutigkeiten nicht. Fehlentscheidungen, die in den fr\u00fchen Entwicklungsphasen des Systems getroffen wurden, k\u00f6nnen einem Programmierer viele Jahre sp\u00e4ter unangenehme \u00dcberraschungen bereiten.<\/p>\n<h2>Zusammenfassung: Der Weg zu 5 Millionen Codezeilen und neuen Horizonten<\/h2>\n<p>\nDas Projekt mypy hat einen langen Weg zur\u00fcckgelegt \u2014 von den fr\u00fchen Prototypen bis hin zu einem System, das die Typen von Produktionscode mit einem Umfang von 4 Millionen Zeilen kontrolliert. Im Laufe der Entwicklung von mypy wurde die Typisierung in Python standardisiert. Heutzutage hat sich rund um die Typisierung von Python-Code ein starkes \u00d6kosystem entwickelt. Darin finden sich Unterst\u00fctzung f\u00fcr Bibliotheken, Hilfsmittel f\u00fcr IDEs und Editoren sowie mehrere Typsysteme, von denen jedes seine eigenen Vor- und Nachteile hat.<\/p>\n<p>Obwohl die Typpr\u00fcfung bei Dropbox bereits als selbstverst\u00e4ndlich angesehen wird, bin ich \u00fcberzeugt, dass wir uns noch in der Anfangsphase der Typisierung von Python-Code befinden. Ich denke, dass sich die Technologien zur Typ\u00fcberpr\u00fcfung weiterhin weiterentwickeln und verbessern werden.<\/p>\n<p>Wenn Sie in Ihrem umfangreichen Python-Projekt noch keine Typpr\u00fcfungen verwendet haben, ist jetzt der ideale Zeitpunkt, um auf statische Typisierung umzusteigen. Ich habe mit einigen gesprochen, die diesen Schritt gemacht haben, und niemand bereut es. Die Typkontrolle verwandelt Python in eine Sprache, die viel besser f\u00fcr die Entwicklung gro\u00dfer Projekte geeignet ist als \u201eherk\u00f6mmliches Python\u201c.<\/p>\n<p><b>Sehr geehrte Leser!<\/b> Nutzen Sie die Typkontrolle in Ihren Python-Projekten?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/bf2bc557ce4481dd87398515bff60e3f.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" alt=\"Der Weg zur Typ\u00fcberpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3\" src=\"\/wp-content\/uploads\/2019\/10\/098d481c25b3afaba9534c686e8f943a.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28992,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-38649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox,\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox,\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Der Weg zur Typpr\u00fcfung von 4 Millionen Zeilen Python-Code. Teil 3 | ProHoster","description":"Wir pr\u00e4sentieren Ihnen den dritten Teil der \u00dcbersetzung des Materials \u00fcber den Weg, den Dropbox beim Implementieren eines Systems zur Typpr\u00fcfung von Python-Code gegangen ist. \u2192 Vorherige Teile: erster und zweiter Teil Erreichung von 4 Millionen Zeilen typisierten Codes. Eine weitere wichtige Herausforderung (die die zweith\u00e4ufigste bei internen Umfragen war) bestand darin, das Codevolumen bei Dropbox zu erh\u00f6hen.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox,","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:25:04+00:00","article:modified_time":"2019-10-31T19:25:04+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"38649","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 22:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:05:23","updated":"2026-01-23 22:54:19"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}