{"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\/cs\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>P\u0159edstavujeme v\u00e1m t\u0159et\u00ed \u010d\u00e1st p\u0159ekladu materi\u00e1lu o cest\u011b, kterou pro\u0161la spole\u010dnost Dropbox p\u0159i zav\u00e1d\u011bn\u00ed syst\u00e9mu kontroly typ\u016f k\u00f3du Python.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3\" src=\"\/wp-content\/uploads\/2019\/10\/757669265e870de604388c66adef814d.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>\u2192 P\u0159edchoz\u00ed \u010d\u00e1sti: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">prvn\u00ed<\/a><\/noindex> a <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">druh\u00e1<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Dos\u00e1hnout 4 milion\u016f \u0159\u00e1dk\u016f typizovan\u00e9ho k\u00f3du<\/h2>\n<p>\nDal\u0161\u00edm d\u016fle\u017eit\u00fdm \u00fakolem (toto byla druh\u00e1 nejpopul\u00e1rn\u011bj\u0161\u00ed ot\u00e1zka, kter\u00e1 tr\u00e1pila ty, kte\u0159\u00ed se \u00fa\u010dastnili intern\u00edch anket) bylo zv\u00fd\u0161en\u00ed objemu k\u00f3du v Dropboxu pokryt\u00e9ho kontrolami typ\u016f. Vyzkou\u0161eli jsme n\u011bkolik p\u0159\u00edstup\u016f k vy\u0159e\u0161en\u00ed tohoto \u00fakolu \u2014 od p\u0159irozen\u00e9ho r\u016fstu objemu typizovan\u00e9 k\u00f3dov\u00e9 z\u00e1kladny po zam\u011b\u0159en\u00ed \u00fasil\u00ed \u010dlen\u016f t\u00fdmu mypy na statick\u00e9 a dynamick\u00e9 automatizovan\u00e9 odvozov\u00e1n\u00ed typ\u016f. Nakonec vznikl dojem, \u017ee neexistuje jednoduch\u00e1 v\u00edt\u011bzn\u00e1 strategie, ale dok\u00e1zali jsme dos\u00e1hnout rychl\u00e9ho r\u016fstu objemu anotovan\u00e9ho k\u00f3du kombinac\u00ed r\u016fzn\u00fdch p\u0159\u00edstup\u016f.<\/p>\n<p>V d\u016fsledku toho v na\u0161em nejv\u011bt\u0161\u00edm Python repozit\u00e1\u0159i (s backendov\u00fdm k\u00f3dem) dos\u00e1hl po\u010det \u0159\u00e1dk\u016f anotovan\u00e9ho k\u00f3du t\u00e9m\u011b\u0159 4 miliony. Pr\u00e1ce na statick\u00e9 typizaci k\u00f3du prob\u00edhala zhruba t\u0159i roky. Mypy nyn\u00ed podporuje r\u016fzn\u00e9 typy zpr\u00e1v o pokryt\u00ed k\u00f3du typy, kter\u00e9 usnad\u0148uj\u00ed sledov\u00e1n\u00ed postupu typizace. Zejm\u00e9na m\u016f\u017eeme generovat zpr\u00e1vy o k\u00f3du s nejistotami v typech, jako jsou nap\u0159\u00edklad explicitn\u00ed pou\u017eit\u00ed typu <code>Jak\u00e9koli<\/code> v anotac\u00edch, kter\u00e9 nelze ov\u011b\u0159it, nebo jako jsou importy extern\u00edch knihoven, kter\u00e9 nemaj\u00ed anotace typ\u016f. V r\u00e1mci projektu na zlep\u0161en\u00ed p\u0159esnosti kontroly typ\u016f v Dropboxu jsme p\u0159isp\u011bli k vylep\u0161en\u00ed definic typ\u016f (takzvan\u00fdch stub soubor\u016f) pro n\u011bkter\u00e9 popul\u00e1rn\u00ed open-source knihovny do centralizovan\u00e9ho Python repozit\u00e1\u0159e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Implementovali jsme (a standardizovali v n\u00e1sleduj\u00edc\u00edch PEP) nov\u00e9 funkce syst\u00e9mu typ\u016f, kter\u00e9 umo\u017e\u0148uj\u00ed pou\u017e\u00edvat p\u0159esn\u011bj\u0161\u00ed typy pro n\u011bkter\u00e9 specifick\u00e9 vzory Pythonu. V\u00fdznamn\u00fdm p\u0159\u00edkladem toho je <code>TypeDict<\/code>, kter\u00fd poskytuje typy pro JSON-podobn\u00e9 slovn\u00edky, kter\u00e9 maj\u00ed pevnou sadu \u0159et\u011bzcov\u00fdch kl\u00ed\u010d\u016f, z nich\u017e ka\u017ed\u00fd m\u00e1 hodnotu vlastn\u00edho typu. Budeme pokra\u010dovat v roz\u0161i\u0159ov\u00e1n\u00ed syst\u00e9mu typ\u016f. Pravd\u011bpodobn\u011b na\u0161\u00edm dal\u0161\u00edm krokem bude zlep\u0161en\u00ed podpory funkc\u00ed Pythonu pro pr\u00e1ci s \u010d\u00edsly.<\/p>\n<p><img decoding=\"async\" alt=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Po\u010det \u0159\u00e1dk\u016f anotovan\u00e9ho k\u00f3du: server<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Po\u010det \u0159\u00e1dk\u016f anotovan\u00e9ho k\u00f3du: klient<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Celkov\u00fd po\u010det \u0159\u00e1dk\u016f anotovan\u00e9ho k\u00f3du<\/i><\/p>\n<p>Zde je p\u0159ehled hlavn\u00edch funkc\u00ed akc\u00ed, kter\u00e9 jsme podnikli k zv\u00fd\u0161en\u00ed objemu anotovan\u00e9ho k\u00f3du v Dropboxu:<\/p>\n<p>P\u0159\u00edsnost anotov\u00e1n\u00ed. Postupn\u011b jsme zvy\u0161ovali po\u017eadavky na p\u0159\u00edsnost anotov\u00e1n\u00ed nov\u00e9ho k\u00f3du. Za\u010dali jsme doporu\u010den\u00edmi linteru, kter\u00e1 navrhovala p\u0159id\u00e1vat anotace do soubor\u016f, kter\u00e9 u\u017e m\u011bly n\u011bkter\u00e9 anotace. Nyn\u00ed vy\u017eadujeme p\u0159\u00edtomnost typov\u00fdch anotac\u00ed v nov\u00fdch Python souborech a ve v\u011bt\u0161in\u011b st\u00e1vaj\u00edc\u00edch soubor\u016f.<\/p>\n<p>Zpr\u00e1vy o typov\u00e1n\u00ed. Ka\u017ed\u00fd t\u00fdden rozes\u00edl\u00e1me t\u00fdm\u016fm zpr\u00e1vy o \u00farovni typov\u00e1n\u00ed jejich k\u00f3du a poskytujeme rady, co by m\u011blo b\u00fdt prioritn\u011b anotov\u00e1no.<\/p>\n<p>Popularizace mypy. Hovo\u0159\u00edme o mypy na r\u016fzn\u00fdch akc\u00edch a komunikujeme s t\u00fdmy, abychom jim pomohli za\u010d\u00edt pou\u017e\u00edvat anotace typ\u016f.<\/p>\n<p>Pr\u016fzkumy. Prov\u00e1d\u00edme pravideln\u00e9 pr\u016fzkumy u\u017eivatel\u016f, abychom zjistili hlavn\u00ed probl\u00e9my. Jsme p\u0159ipraveni j\u00edt dost daleko v \u0159e\u0161en\u00ed t\u011bchto probl\u00e9m\u016f (a\u017e po vytvo\u0159en\u00ed nov\u00e9ho jazyka pro urychlen\u00ed mypy!).<\/p>\n<p>V\u00fdkon. V\u00fdznamn\u011b jsme zlep\u0161ili v\u00fdkon mypy d\u00edky pou\u017eit\u00ed d\u00e9mona a mypyc. Bylo to provedeno, abychom zm\u00edrnili nep\u0159\u00edjemnosti, kter\u00e9 se objevily p\u0159i anotov\u00e1n\u00ed, a abychom mohli pracovat s velk\u00fdmi objemy k\u00f3du.<\/p>\n<p>Integrace s editory. Vytvo\u0159ili jsme n\u00e1stroje pro podporu spu\u0161t\u011bn\u00ed mypy v editorech, kter\u00e9 jsou popul\u00e1rn\u00ed v Dropboxu. Pat\u0159\u00ed sem PyCharm, Vim a VS Code. Toto v\u00fdrazn\u011b zjednodu\u0161ilo proces anotace k\u00f3du a jeho ov\u011b\u0159ov\u00e1n\u00ed. Tyto akce jsou b\u011b\u017en\u00e9 p\u0159i anotaci existuj\u00edc\u00edho k\u00f3du.<\/p>\n<p>Statick\u00e1 anal\u00fdza. Vytvo\u0159ili jsme n\u00e1stroj pro v\u00fdstup podpis\u016f funkc\u00ed pomoc\u00ed n\u00e1stroj\u016f statick\u00e9 anal\u00fdzy. Tento n\u00e1stroj funguje pouze v relativn\u011b jednoduch\u00fdch situac\u00edch, ale pomohl n\u00e1m snadno zv\u00fd\u0161it pokryt\u00ed k\u00f3du typy.<\/p>\n<p>Podpora t\u0159et\u00edch stran. V mnoha na\u0161ich projektech pou\u017e\u00edv\u00e1me sadu n\u00e1stroj\u016f SQLAlchemy. V n\u011bm se pou\u017e\u00edvaj\u00ed dynamick\u00e9 vlastnosti Pythonu, kter\u00e9 typy PEP 484 nejsou schopny p\u0159\u00edmo modelovat. V souladu s PEP 561 jsme vytvo\u0159ili odpov\u00eddaj\u00edc\u00ed stub soubor a napsali plugin pro mypy.<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">open source<\/a><\/noindex>), zlep\u0161uj\u00edc\u00ed podporu SQLAlchemy.<\/p>\n<h2>Obt\u00ed\u017ee, se kter\u00fdmi jsme se setkali<\/h2>\n<p>\nCesta k 4 milion\u016fm \u0159\u00e1dk\u016f typovan\u00e9ho k\u00f3du n\u00e1m nikdy nep\u0159i\u0161la snadn\u00e1. B\u011bhem t\u00e9to cesty jsme narazili na \u0159adu probl\u00e9m\u016f a ud\u011blali n\u011bkolik chyb. Zde je n\u011bkolik probl\u00e9m\u016f, se kter\u00fdmi jsme se setkali. Douf\u00e1me, \u017ee n\u00e1\u0161 p\u0159\u00edb\u011bh pom\u016f\u017ee jin\u00fdm vyhnout se podobn\u00fdm pot\u00ed\u017e\u00edm.<\/p>\n<p>Chyb\u011bj\u00edc\u00ed soubory. Za\u010d\u00ednali jsme s testov\u00e1n\u00edm pouze mal\u00e9ho objemu soubor\u016f. V\u0161e, co nebylo v tomto po\u010dtu zahrnuto, se netestovalo. Sou\u010d\u00e1sti byly do testovac\u00edho seznamu p\u0159id\u00e1v\u00e1ny, jakmile se v nich objevily prvn\u00ed anotace. Pokud n\u011bco poch\u00e1zelo z modulu, kter\u00fd byl mimo testovac\u00ed oblast, \u0161lo o pr\u00e1ci s hodnotami typu <code>Jak\u00e9koli<\/code>, kter\u00e9 se v\u016fbec netestovaly. To vedlo k v\u00fdznamn\u00e9 ztr\u00e1t\u011b p\u0159esnosti typov\u00e1n\u00ed, zejm\u00e9na v ran\u00fdch f\u00e1z\u00edch migrace. Tento p\u0159\u00edstup p\u0159esto fungoval p\u0159ekvapiv\u011b dob\u0159e, a\u010dkoliv typickou situac\u00ed bylo, \u017ee p\u0159id\u00e1n\u00ed soubor\u016f do testovac\u00ed oblasti odhalilo probl\u00e9my v jin\u00fdch \u010d\u00e1stech k\u00f3dov\u00e9 z\u00e1kladny. V nejhor\u0161\u00edm p\u0159\u00edpad\u011b, kdy\u017e byly spojeny dv\u011b izolovan\u00e9 oblasti k\u00f3du, ve kter\u00fdch byly typy ji\u017e nez\u00e1visle ov\u011b\u0159eny, vy\u0161lo najevo, \u017ee typy t\u011bchto oblast\u00ed byly vz\u00e1jemn\u011b nekompatibiln\u00ed. To vedlo k nutnosti prov\u00e9st mnoho zm\u011bn v anotac\u00edch. Dnes, kdy\u017e se ohl\u00ed\u017e\u00edme zp\u011bt, ch\u00e1peme, \u017ee jsme m\u011bli co nejd\u0159\u00edve p\u0159idat z\u00e1kladn\u00ed knihovn\u00ed moduly do testovac\u00ed oblasti typ\u016f mypy. To by na\u0161i pr\u00e1ci u\u010dinilo mnohem p\u0159edv\u00eddateln\u011bj\u0161\u00ed.<\/p>\n<p>Anotace star\u00e9ho k\u00f3du. Kdy\u017e jsme za\u010dali pracovat, m\u011bli jsme p\u0159ibli\u017en\u011b 4 miliony \u0159\u00e1dk\u016f ji\u017e existuj\u00edc\u00edho Python k\u00f3du. Bylo jasn\u00e9, \u017ee anotace tohoto k\u00f3du je \u00fakol, kter\u00fd nen\u00ed zrovna jednoduch\u00fd. Vytvo\u0159ili jsme n\u00e1stroj nazvan\u00fd PyAnnotate, kter\u00fd dok\u00e1\u017ee shroma\u017e\u010fovat informace o typech b\u011bhem testov\u00e1n\u00ed a p\u0159id\u00e1vat anotace typ\u016f do k\u00f3du na z\u00e1klad\u011b shrom\u00e1\u017ed\u011bn\u00fdch informac\u00ed. Nicm\u00e9n\u011b jsme si nev\u0161imli, \u017ee by se tento n\u00e1stroj obzvl\u00e1\u0161t\u011b \u0161iroce roz\u0161\u00ed\u0159il. Shroma\u017e\u010fov\u00e1n\u00ed informac\u00ed o typech bylo pomal\u00e9 a automaticky generovan\u00e9 anotace \u010dasto vy\u017eadovaly spoustu ru\u010dn\u00edch oprav. P\u0159em\u00fd\u0161leli jsme o automatick\u00e9m spu\u0161t\u011bn\u00ed tohoto n\u00e1stroje p\u0159i ka\u017ed\u00e9 kontrole k\u00f3du nebo o shroma\u017e\u010fov\u00e1n\u00ed informac\u00ed o typech na z\u00e1klad\u011b anal\u00fdzy ur\u010dit\u00e9ho men\u0161\u00edho objemu skute\u010dn\u00fdch s\u00ed\u0165ov\u00fdch po\u017eadavk\u016f, ale rozhodli jsme se to neud\u011blat, proto\u017ee jak\u00fdkoli z t\u011bchto p\u0159\u00edstup\u016f by byl p\u0159\u00edli\u0161 riskantn\u00ed.<\/p>\n<p>Na z\u00e1v\u011br lze \u0159\u00edci, \u017ee v\u011bt\u0161ina k\u00f3du byla manu\u00e1ln\u011b anotov\u00e1na jeho vlastn\u00edky. Abychom tento proces nasm\u011brovali spr\u00e1vn\u00fdm sm\u011brem, p\u0159ipravujeme zpr\u00e1vy o zvl\u00e1\u0161\u0165 d\u016fle\u017eit\u00fdch modulech a funkc\u00edch, kter\u00e9 je t\u0159eba anotovat. Nap\u0159\u00edklad je d\u016fle\u017eit\u00e9 opat\u0159it anotacemi typ\u016f knihovn\u00ed modul, kter\u00fd se pou\u017e\u00edv\u00e1 na stovk\u00e1ch m\u00edst. Starou slu\u017ebu, kterou nahrazuje nov\u00e1, v\u0161ak u\u017e nen\u00ed tak d\u016fle\u017eit\u00e9 anotovat. Krom\u011b toho experimentujeme s vyu\u017eit\u00edm statick\u00e9 anal\u00fdzy pro generov\u00e1n\u00ed anotac\u00ed typ\u016f pro star\u00fd k\u00f3d.<\/p>\n<p>Cyklick\u00e9 importy. U\u017e jsem mluvil o cyklick\u00fdch importech (o \u201euzl\u00edc\u00edch z\u00e1vislost\u00ed\u201c), jejich\u017e existence zkomplikovala zrychlen\u00ed mypy. Museli jsme se tak\u00e9 d\u016fkladn\u011b v\u011bnovat podpo\u0159e v\u0161ech typ\u016f idiom\u016f, jejich\u017e vznik zp\u016fsobuj\u00ed tyto cyklick\u00e9 importy. Ned\u00e1vno jsme dokon\u010dili velk\u00fd projekt redesignu syst\u00e9mu, kter\u00fd opravil v\u011bt\u0161inu probl\u00e9m\u016f mypy souvisej\u00edc\u00edch s cyklick\u00fdmi importy. Tyto probl\u00e9my ve skute\u010dnosti vych\u00e1zely z velmi ran\u00fdch dn\u00ed projektu, je\u0161t\u011b z Alore, testovac\u00edho jazyka, na kter\u00fd byl projekt mypy p\u016fvodn\u011b zam\u011b\u0159en. Syntax Alore usnad\u0148uje \u0159e\u0161en\u00ed probl\u00e9m\u016f s cyklick\u00fdmi p\u0159\u00edkazy importu. Modern\u00ed mypy zd\u011bdil n\u011bkter\u00e1 omezen\u00ed ze sv\u00e9 ran\u00e9 prost\u00e9 implementace (kter\u00e1 byla skv\u011bl\u00e1 pro Alore). Python zt\u011b\u017euje pr\u00e1ci s cyklick\u00fdmi importy p\u0159edev\u0161\u00edm kv\u016fli nejasnostem v\u00fdrazu. Nap\u0159\u00edklad b\u011bhem p\u0159i\u0159azen\u00ed hodnoty m\u016f\u017ee b\u00fdt ve skute\u010dnosti definov\u00e1n alias typu. Mypy nen\u00ed v\u017edy schopen takov\u00e9 v\u011bci odhalit, dokud v\u011bt\u0161ina cyklu importu nen\u00ed zpracov\u00e1na. V Alore takov\u00e9 nejasnosti nebyly. Ne\u00fasp\u011b\u0161n\u00e1 rozhodnut\u00ed u\u010din\u011bn\u00e1 v ran\u00fdch f\u00e1z\u00edch v\u00fdvoje syst\u00e9mu mohou program\u00e1torovi p\u0159in\u00e9st nemil\u00e9 p\u0159ekvapen\u00ed po mnoha letech.<\/p>\n<h2>\u00dasp\u011bchy: cesta k 5 milion\u016fm \u0159\u00e1dk\u016f k\u00f3du a k nov\u00fdm horizont\u016fm<\/h2>\n<p>\nProjekt mypy urazil dlouhou cestu \u2013 od ran\u00fdch prototyp\u016f k syst\u00e9mu, kter\u00fd kontroluje typy v\u00fdrobn\u00edho k\u00f3du o objemu 4 milion\u016f \u0159\u00e1dk\u016f. B\u011bhem v\u00fdvoje mypy byla standardizov\u00e1na doporu\u010den\u00ed pro typy v Pythonu. Dnes kolem typizace Python k\u00f3du vznikl siln\u00fd ekosyst\u00e9m. M\u00edsto zde m\u00e1 podpora knihoven, jsou zde n\u00e1stroje pro IDE a editory, existuje n\u011bkolik syst\u00e9m\u016f kontroly typ\u016f, z nich\u017e ka\u017ed\u00fd m\u00e1 sv\u00e9 v\u00fdhody a nev\u00fdhody.<\/p>\n<p>I kdy\u017e je kontrola typ\u016f ji\u017e v Dropboxu pova\u017eov\u00e1na za samoz\u0159ejmost, jsem si jist\u00fd, \u017ee st\u00e1le \u017eijeme na prahu typizace Python k\u00f3du. Mysl\u00edm, \u017ee technologie kontroly typ\u016f budou i nad\u00e1le vyv\u00edjeny a zdokonalov\u00e1ny.<\/p>\n<p>Pokud jste dosud nevyu\u017e\u00edvali kontroly typ\u016f ve sv\u00e9m velk\u00e9m Python projektu, v\u011bzte, \u017ee nyn\u00ed je velmi vhodn\u00e1 doba na p\u0159echod na statickou typizaci. Hovo\u0159il jsem s t\u011bmi, kte\u0159\u00ed tento p\u0159echod uskute\u010dnily. Nikdo z nich toho nelitoval. Kontrola typ\u016f d\u011bl\u00e1 z Pythonu jazyk, kter\u00fd je mnohem l\u00e9pe p\u0159izp\u016fsoben pro v\u00fdvoj velk\u00fdch projekt\u016f ne\u017e \"b\u011b\u017en\u00fd Python\".<\/p>\n<p><b>V\u00e1\u017een\u00ed \u010dten\u00e1\u0159i!<\/b> Pou\u017e\u00edv\u00e1te kontrolu typ\u016f ve sv\u00fdch Python projektech?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 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=\"Cesta k ov\u011b\u0159ov\u00e1n\u00ed typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f k\u00f3du Python. \u010c\u00e1st 3\" src=\"\/wp-content\/uploads\/2019\/10\/098d481c25b3afaba9534c686e8f943a.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Zdroj: <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\/cs\/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=\"cs_CZ\" \/>\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\/cs\/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\udd47Cesta k kontrole typ\u016f 4 milion\u016f \u0159\u00e1dk\u016f Python k\u00f3du. \u010c\u00e1st 3 | ProHoster","description":"P\u0159edstavujeme v\u00e1m t\u0159et\u00ed \u010d\u00e1st p\u0159ekladu materi\u00e1lu o cest\u011b, kterou pro\u0161la spole\u010dnost Dropbox p\u0159i zav\u00e1d\u011bn\u00ed syst\u00e9mu kontroly typ\u016f k\u00f3du Python.","canonical_url":"https:\/\/prohoster.info\/cs\/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":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}