{"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\/no\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"Veien til typekontroll av 4 millioner linjer Python-kode. Del 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Vi presenterer tredje del av oversettelsen av materialet om veien Dropbox har tatt for \u00e5 implementere typekontroll i sin Python-kode.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"Veien til typekontroll av 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 Forrige deler: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">f\u00f8rste<\/a><\/noindex> og <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">andre<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Oppn\u00e5else av 4 millioner linjer typet kode<\/h2>\n<p>\nEn annen viktig oppgave (denne var den nest mest popul\u00e6re problemstillingen blant deltakerne i interne unders\u00f8kelser) var \u00e5 \u00f8ke volumet av kode i Dropbox som dekkes av typekontroller. Vi har fors\u00f8kt flere tiln\u00e6rminger for \u00e5 l\u00f8se denne oppgaven \u2013 fra naturlig vekst av det typede kodegrunnlaget til \u00e5 fokusere teammedlemmene p\u00e5 mypy p\u00e5 statisk og dynamisk automatisk typeutvinning. Til slutt fikk vi inntrykk av at det ikke er en enkel vinnende strategi, men vi klarte \u00e5 oppn\u00e5 rask vekst av volumet av annotert kode ved \u00e5 kombinere flere tiln\u00e6rminger.<\/p>\n<p>Som et resultat n\u00e5dde antallet linjer med annotert kode i v\u00e5rt st\u00f8rste Python-repositorium (med backend-kode) nesten 4 millioner. Arbeidet med statisk typisering av koden ble gjennomf\u00f8rt over omtrent tre \u00e5r. Mypy st\u00f8tter n\u00e5 forskjellige typer rapporter om typekodedekning som forenkler overv\u00e5kingen av typiseringsprosessen. Spesielt kan vi lage rapporter om kode med usikkerheter i typer, slik som eksplisitt bruk av typer <code>Any<\/code> i annotasjoner som ikke kan sjekkes, eller fra import av tredjepartsbiblioteker som ikke har typeannotasjoner. I forbindelse med et prosjekt for \u00e5 forbedre n\u00f8yaktigheten av typekontroll i Dropbox, bidro vi til forbedring av type-definisjoner (s\u00e5kalte stub-filer) for noen popul\u00e6re open-source biblioteker i et sentralisert Python-repositorium <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Vi implementerte (og standardiserte i senere PEP) nye muligheter for typesystemet som gj\u00f8r det mulig \u00e5 bruke mer presise typer for noen spesifikke Python-m\u00f8nstre. Et bemerkelsesverdig eksempel p\u00e5 dette er <code>TypeDict<\/code>, som gir typer for JSON-lignende ordb\u00f8ker med et fast sett av strenge n\u00f8kler, hver av dem har sin egen typeverdi. Vi vil fortsette \u00e5 utvide typesystemet. Sannsynligvis vil v\u00e5rt neste skritt v\u00e6re \u00e5 forbedre st\u00f8tten for Python-funksjoner relatert til tall.<\/p>\n<p><img decoding=\"async\" alt=\"Veien til typekontroll av 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Antall linjer med annotert kode: server<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Veien til typekontroll av 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Antall linjer med annotert kode: klient<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Veien til typekontroll av 4 millioner linjer Python-kode. Del 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Totalt antall linjer med annotert kode<\/i><\/p>\n<p>Her er en oversikt over hovedfunksjonene til de tiltakene vi har utf\u00f8rt for \u00e5 \u00f8ke volumet av annotert kode i Dropbox:<\/p>\n<p>Strenghet i annotering. Vi har gradvis \u00f8kt kravene til strenghet i annoteringen av ny kode. Vi begynte med linters r\u00e5d som foreslo \u00e5 legge til annoteringer i filer som allerede har noen annoteringer. N\u00e5 krever vi tilstedev\u00e6relse av typeannoteringer i nye Python-filer og i de fleste eksisterende filer.<\/p>\n<p>Typeanalyserapporter. Vi sender ukentlig ut rapporter til teamene om niv\u00e5et p\u00e5 typeannoteringene i koden deres, og gir r\u00e5d om hva som b\u00f8r prioriteres i annoteringen.<\/p>\n<p>Popularisering av mypy. Vi informerer om mypy p\u00e5 ulike arrangementer og samarbeider med teamene for \u00e5 hjelpe dem med \u00e5 begynne \u00e5 bruke typeannoteringer.<\/p>\n<p>Unders\u00f8kelser. Vi gjennomf\u00f8rer periodiske brukerunders\u00f8kelser for \u00e5 identifisere de viktigste problemene. Vi er villige til \u00e5 g\u00e5 langt for \u00e5 l\u00f8se disse problemene (inkludert \u00e5 lage et nytt spr\u00e5k for \u00e5 akselerere mypy!).<\/p>\n<p>Ytelse. Vi har betydelig forbedret ytelsen til mypy ved \u00e5 bruke en demon og mypyc. Dette er gjort for \u00e5 jevne ut ulemper som oppst\u00e5r under annoteringen og gi mulighet til \u00e5 arbeide med store mengder kode.<\/p>\n<p>Integrasjon med redakt\u00f8rer. Vi har laget verkt\u00f8y for \u00e5 st\u00f8tte kj\u00f8ring av mypy i redakt\u00f8rer som er popul\u00e6re i Dropbox. Dette inkluderer PyCharm, Vim og VS Code. Dette har betydelig forenklet prosessen med \u00e5 annotere koden og sjekke dens funksjonalitet. Slike tiltak er vanlig ved annotering av eksisterende kode.<\/p>\n<p>Statisk analyse. Vi har utviklet et verkt\u00f8y for \u00e5 gi funksjonssignaturer ved hjelp av statisk analyse. Dette verkt\u00f8yet kan bare fungere i relativt enkle situasjoner, men det har hjulpet oss med \u00e5 \u00f8ke dekningen av koden med typer uten mye ekstra arbeid.<\/p>\n<p>St\u00f8tte for tredjepartsbiblioteker. I mange av prosjektene v\u00e5re bruker vi verkt\u00f8ysettet SQLAlchemy. Det benytter seg av de dynamiske mulighetene i Python som typen PEP 484 ikke kan modellere direkte. I samsvar med PEP 561 har vi laget en passende stub-fil og skrevet et plugin for mypy (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">\u00e5pen kildekode<\/a><\/noindex>), som forbedrer st\u00f8tten for SQLAlchemy.<\/p>\n<h2>Utfordringene vi m\u00f8tte<\/h2>\n<p>\nVeien til 4 millioner linjer med typet kode har ikke alltid v\u00e6rt enkel for oss. P\u00e5 denne veien har vi m\u00f8tt mange hull og gjort flere feil. Her er noen av problemene vi har st\u00f8tt p\u00e5. Vi h\u00e5per at fortellingen om dem kan hjelpe andre med \u00e5 unng\u00e5 lignende problemer.<\/p>\n<p>Glemte filer. Vi begynte arbeidet med \u00e5 sjekke bare et lite antall filer. Alt som ikke var inkludert i disse filene, ble ikke kontrollert. Filer ble lagt til sjekklisten n\u00e5r de fikk sine f\u00f8rste annoteringer. Hvis noe ble importert fra et modul som l\u00e5 utenfor sjekkomr\u00e5det, handlet det om arbeid med typer <code>Any<\/code>, som ikke ble kontrollert i det hele tatt. Dette f\u00f8rte til betydelig tap av typepresisjon, spesielt i de tidlige migrasjonsfasene. Denne tiln\u00e6rmingen har fortsatt fungert overraskende bra, selv om det vanligvis var en situasjon der tillegg av filer til sjekkomr\u00e5det avdekket problemer i andre deler av kodebasen. I det verste tilfellet, n\u00e5r to isolerte kodeomr\u00e5der ble sl\u00e5tt sammen, hvor typene allerede var kontrollert uavhengig av hverandre, viste det seg at typene i disse omr\u00e5dene var inkompatible med hverandre. Dette krevde at en rekke endringer m\u00e5tte gj\u00f8res i annoteringene. N\u00e5, n\u00e5r vi ser tilbake, forst\u00e5r vi at vi skulle ha lagt de grunnleggende bibliotekmodulene i mypy-typekontrollen s\u00e5 tidlig som mulig. Dette ville gjort arbeidet v\u00e5rt mye mer forutsigbart.<\/p>\n<p>Annotering av gammel kode. Da vi begynte arbeidet, hadde vi omtrent 4 millioner linjer med eksisterende Python-kode. Det var klart at annotering av all denne koden ville v\u00e6re en krevende oppgave. Vi skapte et verkt\u00f8y kalt PyAnnotate, som kan samle inn informasjon om typer under kj\u00f8ring av tester og kan legge til typeannotasjoner i koden basert p\u00e5 innsamlet informasjon. Imidlertid la vi merke til at dette verkt\u00f8yet ikke ble spesielt mye brukt. Innsamling av typeinformasjon var treg, og automatisk genererte annotasjoner krevde ofte mye manuell redigering. Vi vurderte \u00e5 kj\u00f8re dette verkt\u00f8yet automatisk ved hver kodesjekk, eller \u00e5 samle inn typeinformasjon basert p\u00e5 analysen av en viss liten mengde reelle nettverksforesp\u00f8rsel, men bestemte oss for ikke \u00e5 gj\u00f8re dette, da noen av disse tiln\u00e6rmingene var for risikable.<\/p>\n<p>Til slutt kan det bemerkes at det meste av koden ble manuelt annotert av eierne. For \u00e5 styre denne prosessen i riktig retning forbereder vi rapporter om spesielt viktige moduler og funksjoner som m\u00e5 annoteres. For eksempel er det viktig \u00e5 gi typeannotasjoner til bibliotekmodulen som brukes p\u00e5 hundrevis av steder. Men det er ikke s\u00e5 viktig \u00e5 annotere en gammel tjeneste som blir erstattet av en ny. I tillegg eksperimenterer vi med bruk av statisk analyse for \u00e5 generere typeannotasjoner for gammel kode.<\/p>\n<p>Sirkul\u00e6re importerer. Ovenfor snakket jeg om sirkul\u00e6re importerer (eller \"knotter av avhengigheter\"), eksistensen av hvilke kompliserte akselerasjonen av mypy. I tillegg m\u00e5tte vi jobbe hardt for \u00e5 gi mypy st\u00f8tte for alle typer idiomer, hvor \u00e5rsaken til at disse sirkul\u00e6re importene oppstod. Nylig fullf\u00f8rte vi et stort prosjekt for redesign av systemet, som l\u00f8ste de fleste av mypy-problemene relatert til sirkul\u00e6re importer. Disse problemene stammer faktisk fra de tidlige dagene av prosjektet, helt fra Alore, programmeringsspr\u00e5ket som prosjektet mypy opprinnelig var rettet mot. Syntaksen til Alore gj\u00f8r det enkelt \u00e5 l\u00f8se problemer med sirkul\u00e6re importkommandoer. Den moderne mypy har arvet noen begrensninger fra sin tidlige enkle implementering (som fungerte utmerket for Alore). Python kompliserer arbeidet med sirkul\u00e6re importerer hovedsakelig p\u00e5 grunn av tvetydighet i uttrykk. For eksempel kan et typealias faktisk bli definert i l\u00f8pet av en tildelingsoperasjon. Mypy er ikke alltid i stand til \u00e5 oppdage slike ting f\u00f8r mesteparten av importsyklusen er behandlet. I Alore var det ingen slike tvetydigheter. Uheldige avgj\u00f8relser tatt i de tidlige utviklingsfasene av systemet kan gi programmereren en ubehagelig overraskelse mange \u00e5r senere.<\/p>\n<h2>Konklusjoner: Veien til 5 millioner linjer med kode og nye horisonter<\/h2>\n<p>\nProsjektet mypy har kommet en lang vei \u2014 fra tidlige prototyper til et system som kontrollerer typer i produksjonskode p\u00e5 4 millioner linjer. Under utviklingen av mypy ble det gjort standardisering av typehint i Python. I dag har det utviklet seg et kraftig \u00f8kosystem rundt typingen av Python-kode. Det er rom for st\u00f8tte for biblioteker, det finnes hjelpemidler for IDE-er og redakt\u00f8rer, og det er flere typekontrollsystemer, hver med sine egne fordeler og ulemper.<\/p>\n<p>Selv om typekontroll allerede betraktes som en selvf\u00f8lge i Dropbox, er jeg sikker p\u00e5 at vi fortsatt lever i begynnelsen av typingen av Python-kode. Jeg tror at teknologien for typekontroll vil fortsette \u00e5 utvikle seg og forbedres.<\/p>\n<p>Dersom du ikke har brukt typekontroll i ditt storskala Python-prosjekt, vet at n\u00e5 er et utmerket tidspunkt for \u00e5 begynne overgangen til statisk typing. Jeg har snakket med de som har gjort en slik overgang, og ingen av dem har angret. Typekontroll gj\u00f8r Python til et spr\u00e5k som egner seg mye bedre enn \"vanlig Python\" for utvikling av store prosjekter.<\/p>\n<p><b>Kj\u00e6re lesere!<\/b> Bruker du typekontroll i Python-prosjektene dine?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"Veien til typekontroll av 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=\"Veien til typekontroll av 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.5 - 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\/no\/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.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"nn_NO\" \/>\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\/no\/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\udd47Veien til typekontroll av 4 millioner linjer Python-kode. Del 3 | ProHoster","description":"Vi presenterer tredje del av oversettelsen av materialet om veien Dropbox har tatt for \u00e5 implementere typekontroll i sin Python-kode.","canonical_url":"https:\/\/prohoster.info\/no\/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":"nn_NO","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\/no\/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\/no\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}