{"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\/da\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Vi pr\u00e6senterer hermed den tredje del af overs\u00e6ttelsen af materialet om den rejse, som Dropbox har gennemg\u00e5et med implementeringen af deres Python-kode typekontrolsystem.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/757669265e870de604388c66adef814d.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>\u2192 Tidligere dele: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">den f\u00f8rste<\/a><\/noindex> og <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">anden<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Opn\u00e5else af 4 millioner linjer typeannoteret kode<\/h2>\n<p>\nEn anden vigtig opgave (dette var det n\u00e6stmest popul\u00e6re emne blandt dem, der deltog i de interne sp\u00f8rgeskemaer) var at \u00f8ge m\u00e6ngden af kode i Dropbox, der var d\u00e6kket af typekontrol. Vi pr\u00f8vede flere tilgange til at l\u00f8se denne opgave - fra den naturlige v\u00e6kst af den typeannoterede kodebase til at fokusere p\u00e5 indsatsen fra teamet mypy p\u00e5 statisk og dynamisk automatiseret typedeclaration. I sidste ende havde vi indtrykket, at der ikke var nogen simpel vindende strategi, men vi form\u00e5ede hurtigt at \u00f8ge m\u00e6ngden af annoteret kode ved at kombinere mange tilgange.<\/p>\n<p>Som resultat er antallet af linjer af annoteret kode i vores st\u00f8rste Python-repository (med backend-kode) n\u00e5et n\u00e6sten op p\u00e5 4 millioner. Arbejdet med statisk typekontrol blev udf\u00f8rt over cirka tre \u00e5r. Mypy underst\u00f8tter nu forskellige former for d\u00e6kningsrapporter om typer, der g\u00f8r det lettere at overv\u00e5ge fremskridtene i typeannotationen. Is\u00e6r kan vi generere rapporter om kode med usikkerheder i typer, s\u00e5som eksplicit brug af typer <code>Any<\/code> i annotationer, der ikke kan verificeres, eller n\u00e5r der importeres tredjepartsbiblioteker, hvor der ikke er nogen typeannotering. Som en del af projektet for at forbedre n\u00f8jagtigheden af typekontrol i Dropbox har vi bidraget til forbedringen af type-definitionerne (de s\u00e5kaldte stub-filer) for nogle popul\u00e6re open source-biblioteker i et centraliseret Python-repository <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Vi har implementeret (og standardiseret i de efterf\u00f8lgende PEP'er) nye funktioner i typesystemet, der muligg\u00f8r brugen af mere pr\u00e6cise typer til nogle specifikke Python-m\u00f8nstre. Et bem\u00e6rkelsesv\u00e6rdigt eksempel p\u00e5 dette er <code>TypeDict<\/code>, som tilbyder typer til JSON-lignende ordb\u00f8ger med et fast s\u00e6t af strengn\u00f8gler, hvor hver enkelt har en v\u00e6rdi af sin egen type. Vi vil forts\u00e6tte med at udvide typesystemet. Vores n\u00e6ste skridt vil sandsynligvis v\u00e6re at forbedre underst\u00f8ttelsen af Python-funktioner til at arbejde med tal.<\/p>\n<p><img decoding=\"async\" alt=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Antallet af linjer af annoteret kode: server<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Antallet af annoteret kode: klient<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Det samlede antal linjer af annoteret kode<\/i><\/p>\n<p>Her er et overblik over de vigtigste funktioner i de handlinger, vi har udf\u00f8rt for at \u00f8ge m\u00e6ngden af annoteret kode i Dropbox:<\/p>\n<p>Strenghed i annotering. Vi har gradvist h\u00e6vet kravene til strengheden ved annotering af ny kode. Vi startede med at anbefale linsteren, som foreslog at tilf\u00f8je annotationer i filer, der allerede har nogle annotationer. Nu kr\u00e6ver vi, at der er typeannotationer i nye Python-filer og i de fleste eksisterende filer.<\/p>\n<p>Typingsrapporter. Vi sender ugentligt rapporter til teams om niveauet af typinger i deres kode og giver r\u00e5d om, hvad der b\u00f8r annoteres f\u00f8rst.<\/p>\n<p>Popularisering af mypy. Vi pr\u00e6senterer mypy ved forskellige arrangementer og interagerer med teams for at hj\u00e6lpe dem med at begynde at bruge typeannotationer.<\/p>\n<p>Unders\u00f8gelser. Vi gennemf\u00f8rer periodiske brugerunders\u00f8gelser for at identificere de st\u00f8rste problemer. Vi er villige til at g\u00e5 langt for at l\u00f8se disse problemer (inklusive at skabe et nyt sprog for at fremskynde mypy!).<\/p>\n<p>Ydeevne. Vi har markant forbedret ydeevnen af mypy ved at bruge en daemon og mypyc. Dette blev gjort for at udj\u00e6vne ulemperne ved annotering og for at kunne arbejde med store m\u00e6ngder kode.<\/p>\n<p>Integration med redakt\u00f8rer. Vi har skabt v\u00e6rkt\u00f8jer til st\u00f8tte for k\u00f8rsel af mypy i redakt\u00f8rer, der er popul\u00e6re i Dropbox. Dette inkluderer PyCharm, Vim og VS Code. Det har betydeligt forenklet processen med at annotere kode og kontrollere dens funktionalitet. S\u00e5danne handlinger er typiske, n\u00e5r man annoterer eksisterende kode.<\/p>\n<p>Statisk analyse. Vi har skabt et v\u00e6rkt\u00f8j til at generere funktionssignaturer ved hj\u00e6lp af statisk analyse. Dette v\u00e6rkt\u00f8j kan kun fungerer i forholdsvis enkle situationer, men det har hjulpet os med at \u00f8ge type-d\u00e6kningen af koden uden st\u00f8rre anstrengelser.<\/p>\n<p>Support til tredjepartsbiblioteker. I mange af vores projekter bruger vi v\u00e6rkt\u00f8js\u00e6ttet SQLAlchemy. Det bruger de dynamiske funktioner i Python, som PEP 484-typerne ikke kan modellere direkte. I henhold til PEP 561 har vi oprettet den relevante stub-fil og skrevet et plugin til mypy.<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">open source<\/a><\/noindex>), som forbedrer SQLAlchemy-support.<\/p>\n<h2>Udfordringer, vi st\u00f8dte p\u00e5<\/h2>\n<p>\nVejen til 4 millioner linjer af typet kode har ikke altid v\u00e6ret let for os. P\u00e5 denne rejse har vi m\u00f8dt mange forhindringer og beg\u00e5et flere fejl. Her er nogle af de problemer, vi har st\u00e5et overfor. Vi h\u00e5ber, at fort\u00e6llingen om dem vil hj\u00e6lpe andre med at undg\u00e5 lignende problemer.<\/p>\n<p>Manglede filer. Vi begyndte arbejdet med at kontrollere kun et lille antal filer. Alt, der ikke var inkluderet i disse filer, blev ikke kontrolleret. Filer blev tilf\u00f8jet til kontrollisten, n\u00e5r de f\u00f8rste annotationer dukkede op i dem. Hvis noget blev importeret fra et modul uden for kontrolomr\u00e5det, var der tale om at arbejde med v\u00e6rdier, der slet ikke blev verificeret. <code>Any<\/code>, hvilket f\u00f8rte til betydelige tab af typepr\u00e6cision, is\u00e6r i de tidlige faser af migrationen. Denne tilgang fungerede stadig overraskende godt, selvom det typisk var en situation, hvor tilf\u00f8jelsen af filer til kontrolomr\u00e5det afd\u00e6kkede problemer i andre dele af kodebasen. I v\u00e6rste fald, n\u00e5r to isolerede kodeomr\u00e5der, hvor typerne allerede uafh\u00e6ngigt var blevet kontrolleret, blev sammenlagt, viste det sig, at typerne i disse omr\u00e5der var inkompatible med hinanden. Dette f\u00f8rte til, at vi m\u00e5tte foretage mange \u00e6ndringer i annotationerne. Nu, n\u00e5r vi ser tilbage, forst\u00e5r vi, at vi burde have tilf\u00f8jet grundl\u00e6ggende biblioteksmoduler til typekontrolomr\u00e5det med det samme. Det ville have gjort vores arbejde meget mere forudsigeligt.<\/p>\n<p>Annotering af gammel kode. Da vi begyndte vores arbejde, havde vi omkring 4 millioner linjer eksisterende Python-kode. Det var klart, at annotering af al denne kode var en udfordrende opgave. Vi skabte et v\u00e6rkt\u00f8j kaldet PyAnnotate, som kan indsamle typeoplysninger under testk\u00f8rsler og tilf\u00f8je typeannoteringer til koden baseret p\u00e5 de indsamlede oplysninger. Dog s\u00e5 vi ikke nogen bred implementering af dette v\u00e6rkt\u00f8j. Indsamlingen af typeoplysninger var langsom, og automatisk genererede annoteringer kr\u00e6vede ofte mange manuelle korrektioner. Vi overvejede at k\u00f8re dette v\u00e6rkt\u00f8j automatisk ved hver kodegennemgang eller at indsamle typeoplysninger baseret p\u00e5 analysen af et lille antal faktiske netv\u00e6rksanmodninger, men besluttede ikke at g\u00f8re dette, da nogen af disse tilgange var for risikable.<\/p>\n<p>Som resultat kan det bem\u00e6rkes, at st\u00f8rstedelen af koden blev annoteret manuelt af dens ejere. For at styre denne proces i den rigtige retning forbereder vi rapporter om is\u00e6r vigtige moduler og funktioner, der skal annoteres. For eksempel er det vigtigt at tilf\u00f8je typeannoteringer til biblioteksmodulet, der bruges mange steder. Men for den gamle service, som bliver erstattet af den nye, er annoteringen ikke s\u00e5 vigtig l\u00e6ngere. Derudover eksperimenterer vi med at bruge statisk analyse til at generere typeannoteringer for den gamle kode.<\/p>\n<p>Cirkul\u00e6re importer. Tidligere har jeg talt om cirkul\u00e6re importer (om \"afh\u00e6ngighedsknuder\"), hvis eksistens har gjort det sv\u00e6rere at accelerere mypy. Vi har desuden v\u00e6ret n\u00f8dt til at arbejde h\u00e5rdt p\u00e5 at give mypy st\u00f8tte til alle former for idiomer, hvis opst\u00e5en skyldes disse cirkul\u00e6re importer. For nylig afsluttede vi et stort redesign af systemet, som rettede de fleste problemer med mypy relateret til cirkul\u00e6re importer. Disse problemer stammer faktisk fra de tidlige dage af projektet, helt tilbage fra Alore, et undervisningssprog, som projektet mypy oprindeligt blev orienteret imod. Alore-syntaxen g\u00f8r det let at l\u00f8se problemer med cirkul\u00e6re importbefalinger. Moderne mypy har arvet nogle begr\u00e6nsninger fra sin tidlige enkelthed (som var ideel til Alore). Python komplicerer arbejdet med cirkul\u00e6re importer hovedsageligt p\u00e5 grund af tvetydighed i udtryk. For eksempel kan en typealias faktisk blive defineret under en tildelingsoperation. Mypy er ikke altid i stand til at identificere s\u00e5danne ting, indtil det meste af importcyklussen er blevet behandlet. I Alore fandtes der ikke s\u00e5danne tvetydigheder. Uheldige beslutninger truffet i de tidlige udviklingsfaser af systemet kan overraske programm\u00f8rerne mange \u00e5r senere.<\/p>\n<h2>Konklusioner: Vejen til 5 millioner linjer kode og nye horisonter<\/h2>\n<p>\nProjektet mypy har gennemg\u00e5et en lang rejse - fra tidlige prototyper til et system, der kontrollerer typerne af produktionskode p\u00e5 4 millioner linjer. Undervejs er der blevet standardiseret type-hints i Python. I dag er der udviklet et kraftfuldt \u00f8kosystem omkring typificering af Python-kode. Det rummer st\u00f8tte til biblioteker, der findes v\u00e6rkt\u00f8jer til IDE'er og redakt\u00f8rer, og der er flere systems til typekontrol, som hver har sine fordele og ulemper.<\/p>\n<p>Selvom typekontrol allerede opfattes som en selvf\u00f8lgelighed i Dropbox, er jeg sikker p\u00e5, at vi stadig lever i den tidlige fase af Python-kodetypering. Jeg tror, at teknologierne til typekontrol vil forts\u00e6tte med at udvikle sig og forbedre sig.<\/p>\n<p>Hvis du endnu ikke har brugt typekontrol i dit store Python-projekt, s\u00e5 ved, at nu er et fantastisk tidspunkt at begynde overgangen til statisk typning. Jeg har talt med dem, der har gennemf\u00f8rt en s\u00e5dan overgang. Ingen af dem har fortrudt det. Typekontrol g\u00f8r Python til et sprog, der er meget bedre egnet til udvikling af store projekter end \"almindelig Python\".<\/p>\n<p><b>K\u00e6re l\u00e6sere!<\/b> Bruger du typekontrol i dine Python-projekter?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 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=\"Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/098d481c25b3afaba9534c686e8f943a.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Kilde: <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.3 - 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\/da\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Vejen til typekontrol af 4 millioner linjer Python-kode. Del 3 | ProHoster","description":"Vi pr\u00e6senterer hermed den tredje del af overs\u00e6ttelsen af materialet om den rejse, som Dropbox har gennemg\u00e5et med implementeringen af deres Python-kode typekontrolsystem.","canonical_url":"https:\/\/prohoster.info\/da\/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":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}