{"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 der \u00dcbersetzung des Materials \u00fcber den Weg, den das Unternehmen Dropbox bei der Einf\u00fchrung eines Typsystems f\u00fcr Python-Code eingeschlagen hat.<\/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 Fr\u00fchere Teile: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">erste<\/a><\/noindex> und <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">zweite<\/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 Problem, das Teilnehmer an internen Umfragen besch\u00e4ftigte) war die Erh\u00f6hung des Umfangs des Codes in Dropbox, der durch Typpr\u00fcfungen abgedeckt ist. Wir haben mehrere Ans\u00e4tze ausprobiert, um dieses Ziel zu erreichen \u2014 von nat\u00fcrlichem Wachstum der typisierten Codebasis bis hin zur Konzentration der Bem\u00fchungen der mypy-Teammitglieder auf statische und dynamische automatisierte Typableitungen. Letztendlich entstand der Eindruck, dass es keine einfache Strategie zum Erfolg gibt, aber wir konnten ein schnelles Wachstum des angrenzten Codes erreichen, indem wir eine Vielzahl von Ans\u00e4tzen kombinierten.<\/p>\n<p>In unserem gr\u00f6\u00dften Python-Repository (mit Backend-Code) hat die Anzahl der annotierten Codezeilen fast 4 Millionen erreicht. Die Arbeit an der statischen Typisierung des Codes wurde \u00fcber etwa drei Jahre durchgef\u00fchrt. Mypy unterst\u00fctzt jetzt verschiedene Arten von Berichten zur Typabdeckung, die die \u00dcberwachung des Typisierungsprozesses erleichtern. Insbesondere k\u00f6nnen wir Berichte \u00fcber Code mit Unklarheiten in den Typen erstellen, wie etwa die explizite Verwendung des Typs <code>Any<\/code> in Anmerkungen, die nicht \u00fcberpr\u00fcft werden k\u00f6nnen, oder wie bei der Einfuhr von Drittanbieterbibliotheken, die keine Typanmerkungen enthalten. Im Rahmen des Projekts zur Verbesserung der Typpr\u00fcfungsgenauigkeit in Dropbox haben wir zur Verbesserung der Typdefinitionen (sogenannten Stub-Dateien) f\u00fcr einige beliebte Open-Source-Bibliotheken im zentralisierten Python-Repository beigetragen. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Wir haben neue Funktionen des Typsystems implementiert (und in sp\u00e4teren PEP standardisiert), die es erm\u00f6glichen, pr\u00e4zisere Typen f\u00fcr bestimmte spezifische Python-Muster zu verwenden. Ein bemerkenswertes Beispiel daf\u00fcr ist <code>TypeDict<\/code>, das Typen f\u00fcr JSON-\u00e4hnliche W\u00f6rterb\u00fccher bereitstellt, die eine feste Menge von String-Schl\u00fcsseln haben, von denen jeder einen Wert eines eigenen Typs hat. Wir werden das Typsystem weiterhin erweitern. Wahrscheinlich wird unser n\u00e4chster Schritt die Verbesserung der Unterst\u00fctzung f\u00fcr die numerischen F\u00e4higkeiten von Python 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: Kunde<\/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>Gesamtzahl der annotierten Codezeilen<\/i><\/p>\n<p>Hier ist eine \u00dcbersicht \u00fcber die wichtigsten Merkmale der Ma\u00dfnahmen, die wir zur Erh\u00f6hung des Umfangs des annotierten Codes in Dropbox ergriffen haben:<\/p>\n<p>Strenge der Annotation. Wir haben die Anforderungen an die Strenge der Annotation neuer Codes schrittweise erh\u00f6ht. Wir haben mit den Empfehlungen des Linters begonnen, die anrieten, Annotationen in Dateien hinzuzuf\u00fcgen, in denen bereits einige Annotationen vorhanden sind. Jetzt fordern wir Typannotationen in neuen Python-Dateien und in den meisten bestehenden Dateien.<\/p>\n<p>Berichte \u00fcber die Typisierung. W\u00f6chentlich senden wir den Teams Berichte \u00fcber den Grad der Typisierung ihres Codes und geben Ratschl\u00e4ge, was zuerst annotiert werden sollte.<\/p>\n<p>Popularisierung von mypy. Wir sprechen auf verschiedenen Veranstaltungen \u00fcber mypy und kommunizieren mit den Teams, um ihnen zu helfen, Typannotations zu verwenden.<\/p>\n<p>Umfragen. Wir f\u00fchren regelm\u00e4\u00dfige Umfragen unter den Nutzern durch, um die Hauptprobleme zu identifizieren. Wir sind bereit, weit zu gehen, um diese Probleme zu l\u00f6sen (bis hin zur Schaffung einer neuen Sprache zur Beschleunigung von mypy!).<\/p>\n<p>Leistung. Wir haben die Leistung von mypy erheblich verbessert, indem wir einen Daemon und mypyc eingesetzt haben. Dies wurde getan, um die Unannehmlichkeiten w\u00e4hrend des Annotierens zu minimieren und um die Arbeit mit gro\u00dfen Codebasen zu erm\u00f6glichen.<\/p>\n<p>Integration mit Editoren. Wir haben Werkzeuge zur Unterst\u00fctzung der Ausf\u00fchrung von mypy in den bei Dropbox beliebten Editoren entwickelt. Dazu geh\u00f6ren PyCharm, Vim und VS Code. Dies hat den Prozess des Annotierens und Testens des Codes erheblich erleichtert. Solche Ma\u00dfnahmen sind normalerweise charakteristisch f\u00fcr das Annotieren von vorhandenem Code.<\/p>\n<p>Statische Analyse. Wir haben ein Tool zur Ausgabe von Funktionssignaturen unter Verwendung statischer Analysetools entwickelt. Dieses Tool kann nur in vergleichsweise einfachen Situationen arbeiten, hat uns aber geholfen, den Typabdeckungsgrad des Codes ohne gro\u00dfen Aufwand zu erh\u00f6hen.<\/p>\n<p>Unterst\u00fctzung von Drittanbieterbibliotheken. In vielen unserer Projekte verwenden wir das Toolset SQLAlchemy. Dabei kommen die dynamischen M\u00f6glichkeiten von Python zum Einsatz, die die Typen von PEP 484 nicht direkt modellieren k\u00f6nnen. Entsprechend PEP 561 haben wir die entsprechende Stub-Datei erstellt und ein Plugin f\u00fcr mypy geschrieben.<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">Open Source<\/a><\/noindex>), die die SQLAlchemy-Unterst\u00fctzung verbessert.<\/p>\n<h2>Die Schwierigkeiten, mit denen wir konfrontiert waren<\/h2>\n<p>\nDer Weg zu 4 Millionen Zeilen typisierten Codes war nicht immer einfach f\u00fcr uns. Auf diesem Weg sind wir auf zahlreiche Stolpersteine gesto\u00dfen und haben einige Fehler gemacht. Hier sind einige der Probleme, mit denen wir konfrontiert waren. Wir hoffen, dass unser Bericht \u00fcber diese Probleme anderen helfen kann, \u00e4hnliche Herausforderungen zu vermeiden.<\/p>\n<p>Fehlende Dateien. Wir haben mit der \u00dcberpr\u00fcfung nur einer kleinen Anzahl von Dateien begonnen. Alles, was nicht zu diesen Dateien geh\u00f6rte, wurde nicht \u00fcberpr\u00fcft. Dateien wurden zur \u00dcberpr\u00fcfung hinzugef\u00fcgt, sobald die ersten Annotations vorhanden waren. Wenn etwas aus einem Modul importiert wurde, das au\u00dferhalb des \u00dcberpr\u00fcfungsbereichs 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. Dieser Ansatz hat \u00fcberraschend gut funktioniert, obwohl es typisch war, dass die Hinzuf\u00fcgung von Dateien zur \u00dcberpr\u00fcfung Probleme in anderen Teilen der Codebasis aufdeckte. Im schlimmsten Fall, wenn zwei isolierte Codebereiche zusammengef\u00fchrt wurden, in denen die Typen unabh\u00e4ngig voneinander bereits gepr\u00fcft worden waren, stellte sich heraus, dass die Typen dieser Bereiche nicht miteinander kompatibel waren. Dies erforderte viele \u00c4nderungen an den Annotations. Jetzt, im R\u00fcckblick, verstehen wir, dass wir die grundlegenden Bibliotheksmodule so fr\u00fch wie m\u00f6glich in den Typpr\u00fcfungsbereich von mypy einf\u00fcgen sollten. Das h\u00e4tte unsere Arbeit viel vorhersehbarer gemacht.<\/p>\n<p>Annotierung von altem Code. Als wir mit der Arbeit begannen, hatten wir etwa 4 Millionen Zeilen bereits bestehenden Python-Codes. Es war klar, dass die Annotierung all dieses Codes eine schwierige Aufgabe war. Wir entwickelten ein Tool namens PyAnnotate, das zur Laufzeit w\u00e4hrend der Tests Informationen \u00fcber Typen sammeln kann und in der Lage ist, basierend auf den gesammelten Informationen Typannotationen in den Code hinzuzuf\u00fcgen. Eine besonders breite Einf\u00fchrung dieses Tools haben wir jedoch nicht wahrgenommen. Das Sammeln von Typinformationen verlief langsam, und automatisch generierte Annotationen erforderten oft viele manuelle Anpassungen. Wir dachten dar\u00fcber nach, dieses Tool bei jedem Code-Check automatisch auszuf\u00fchren oder Typinformationen basierend auf der Analyse einer kleinen Menge realer Netzwerkabfragen zu sammeln, haben uns jedoch dagegen entschieden, da jeder dieser Ans\u00e4tze zu riskant war.<\/p>\n<p>Abschlie\u00dfend kann gesagt werden, dass der gr\u00f6\u00dfte Teil des Codes manuell von seinen Besitzern 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. Es ist beispielsweise wichtig, den Bibliotheksmodul, der an vielen Stellen verwendet wird, mit Typannotationen zu versehen. Ein alter Service, der durch einen neuen ersetzt wird, muss hingegen nicht mehr so wichtig annotiert werden. Au\u00dferdem experimentieren wir mit dem Einsatz statischer Analysen zur Generierung von Typannotationen f\u00fcr alten Code.<\/p>\n<p>Zyklische Importe. Ich habe bereits \u00fcber zyklische Importe (\u00fcber \"Abh\u00e4ngigkeitsstr\u00e4nge\") gesprochen, deren Existenz die Beschleunigung von mypy erschwert hat. Dar\u00fcber hinaus mussten wir intensiv daran arbeiten, mypy mit Unterst\u00fctzung f\u00fcr alle Arten von Idiomen auszustatten, die durch diese zyklischen Importe verursacht werden. K\u00fcrzlich haben wir ein gro\u00dfes Redesign-Projekt abgeschlossen, das die meisten Probleme von mypy in Bezug auf zyklische Importe behoben hat. Diese Probleme stammen tats\u00e4chlich aus den sehr fr\u00fchen Tagen des Projekts, noch von Alore, der Lehrsprache, auf die mypy urspr\u00fcnglich ausgerichtet war. Die Syntax von Alore erm\u00f6glicht es, Probleme zyklischer Importanweisungen leicht zu l\u00f6sen. Modernes mypy hat einige Einschr\u00e4nkungen von seiner fr\u00fchen, schlichten Implementierung geerbt (die sich gut f\u00fcr Alore eignete). Python erschwert die Arbeit mit zyklischen Importen haupts\u00e4chlich aufgrund von Mehrdeutigkeiten in den Ausdr\u00fccken. Zum Beispiel kann bei einer Zuweisung der tats\u00e4chliche Typalias bestimmt werden. Mypy ist nicht immer in der Lage, solche Dinge zu erkennen, bis ein gro\u00dfer Teil des Importzyklus bearbeitet ist. In Alore gab es solche Mehrdeutigkeiten nicht. Fehlentscheidungen, die in fr\u00fchen Entwicklungsphasen des Systems getroffen wurden, k\u00f6nnen Programmierern viele Jahre sp\u00e4ter unangenehme \u00dcberraschungen bereiten.<\/p>\n<h2>Ergebnisse: Der Weg zu 5 Millionen Codezeilen und neuen Horizonten<\/h2>\n<p>\nDas mypy-Projekt hat einen langen Weg hinter sich \u2014 von fr\u00fchen Prototypen bis zu einem System, mit dem die Typen von Produktionscode mit insgesamt 4 Millionen Zeilen kontrolliert werden. Im Laufe der Entwicklung von mypy wurde eine Standardisierung der Typ-Hinweise in Python umgesetzt. Heutzutage hat sich um die Typisierung von Python-Code ein leistungsf\u00e4higes \u00d6kosystem entwickelt. Es gibt Unterst\u00fctzung f\u00fcr Bibliotheken, Hilfsmittel f\u00fcr IDEs und Editoren, und mehrere Typpr\u00fcfungssysteme, 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 mir sicher, dass wir uns immer noch in der Fr\u00fchzeit der Typisierung von Python-Code befinden. Ich denke, dass sich die Technologien zur Typpr\u00fcfung weiterhin entwickeln und verbessern werden.<\/p>\n<p>Wenn Sie Typ\u00fcberpr\u00fcfungen in Ihrem gro\u00dfangelegten Python-Projekt noch nicht verwendet haben, wissen Sie, dass jetzt der passende Zeitpunkt ist, um auf statische Typisierung umzusteigen. Ich habe mit vielen gesprochen, die diesen \u00dcbergang vollzogen haben. Niemand von ihnen hat es bereut. Die Typkontrolle verwandelt Python in eine Sprache, die deutlich besser geeignet ist f\u00fcr die Entwicklung gro\u00dfer Projekte als \u201enormales Python\u201c.<\/p>\n<p><b>Liebe 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 5.0.1.1 - 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.\" \/>\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) 5.0.1.1\" \/>\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.\" \/>\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 Typ\u00fcberpr\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 das Unternehmen Dropbox bei der Einf\u00fchrung eines Typsystems f\u00fcr Python-Code eingeschlagen hat.","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.","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":{"focus":[],"additional":[]},"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-08-11 12:50:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"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}]}}