Path kanggo ngetik 4 yuta baris kode Python. Bagean 2

Dina iki kita nerbitake bagean liya saka terjemahan materi babagan carane Dropbox ngatur jinis kontrol kanggo sawetara yuta baris kode Python.

Path kanggo ngetik 4 yuta baris kode Python. Bagean 2

β†’ Maca bagean siji

Dhukungan jinis resmi (PEP 484)

Kita nganakake eksperimen serius pisanan karo mypy ing Dropbox sajrone Minggu Hack 2014. Minggu Hack minangka acara seminggu sing dianakake dening Dropbox. Sajrone wektu iki, karyawan bisa nindakake apa wae sing dikarepake! Sawetara proyek teknologi Dropbox sing paling misuwur diwiwiti ing acara kaya iki. Minangka asil saka eksperimen iki, kita nyimpulake yen mypy katon janjeni, sanajan proyek kasebut durung siyap digunakake kanthi wiyar.

Ing wektu kasebut, ide standarisasi sistem hinting jinis Python ana ing udara. Nalika aku ngandika, wiwit Python 3.0 iku bisa nggunakake anotasi jinis kanggo fungsi, nanging iki mung ekspresi kasepakatan, tanpa sintaks lan semantik ditetepake. Sajrone eksekusi program, anotasi kasebut, umume, ora digatekake. Sawise Hack Week, kita miwiti nggarap standarisasi semantik. Karya iki mimpin kanggo munculé PEP 484 (Guido van Rossum, Łukasz Langa lan aku kerja sama ing dokumen iki).

Motif kita bisa dideleng saka rong sisi. Kaping pisanan, kita ngarep-arep yen kabeh ekosistem Python bisa nggunakake pendekatan umum kanggo nggunakake pitunjuk jinis (istilah sing digunakake ing Python minangka padha karo "anotasi jinis"). Iki, amarga ana risiko, bakal luwih apik tinimbang nggunakake akeh pendekatan sing ora kompatibel. Kapindho, kita pengin ngrembug babagan mekanisme anotasi jinis kanthi akeh anggota komunitas Python. Kepinginan iki sebagian didikte dening kasunyatan manawa kita ora pengin katon kaya "murtad" saka ide dhasar basa kasebut ing mripate akeh programer Python. Iki minangka basa sing diketik kanthi dinamis, sing dikenal minangka "ngetik bebek". Ing masyarakat, ing awal banget, sikap sing rada curiga marang gagasan ngetik statis ora bisa mbantu nanging muncul. Nanging sentimen kasebut pungkasane ilang sawise dadi jelas yen ngetik statis ora bakal dadi wajib (lan sawise wong ngerti yen pancen migunani).

Sintaks pitunjuk jinis sing pungkasane diadopsi meh padha karo sing didhukung mypy nalika iku. PEP 484 dirilis nganggo Python 3.5 ing 2015. Python dudu basa sing diketik kanthi dinamis. Aku seneng mikir acara iki minangka tonggak penting ing sajarah Python.

Wiwitan migrasi

Ing pungkasan taun 2015, Dropbox nggawe tim telu wong kanggo nggarap mypy. Dheweke kalebu Guido van Rossum, Greg Price lan David Fisher. Wiwit wektu iku, kahanan wiwit berkembang kanthi cepet. Rintangan pisanan kanggo pertumbuhan mypy yaiku kinerja. Kaya sing dakcritakake ing ndhuwur, ing wiwitan proyek, aku mikir babagan nerjemahake implementasi mypy menyang C, nanging ide iki ora ana ing dhaptar saiki. Kita macet nganggo sistem nggunakake interpreter CPython, sing ora cukup cepet kanggo alat kaya mypy. (Proyek PyPy, implementasi Python alternatif karo kompiler JIT, uga ora nulungi kita.)

Untunge, sawetara dandan algoritmik wis mbantu kita ing kene. "Akselerator" kuat pisanan yaiku implementasi pemeriksaan tambahan. Ing idea konco dandan iki prasaja: yen kabeh dependensi modul wis ora diganti wiwit run mypy sadurungΓ©, banjur kita bisa nggunakake data cache sak run sadurungΓ© nalika nggarap dependensi. Kita mung kudu mriksa jinis file sing diowahi lan file sing gumantung. Mypy malah luwih maju: yen antarmuka eksternal modul ora diganti, mypy nganggep yen modul liyane sing ngimpor modul iki ora perlu dicenthang maneh.

Pemeriksa tambahan wis mbantu kita nalika menehi anotasi akeh kode sing wis ana. Intine yaiku proses iki biasane melu akeh mypy iteratif amarga anotasi mboko sithik ditambahake menyang kode lan mboko sithik. Mlaku pisanan mypy isih alon banget amarga akeh dependensi sing kudu dipriksa. Banjur, kanggo nambah kahanan, kita ngetrapake mekanisme caching remot. Yen mypy ndeteksi manawa cache lokal kemungkinan wis kedaluwarsa, bakal ngundhuh snapshot cache saiki kanggo kabeh basis kode saka repositori terpusat. Banjur nindakake mriksa tambahan nggunakake snapshot iki. Iki wis njupuk siji langkah luwih gedhe kanggo nambah kinerja mypy.

Iki minangka periode adopsi kanthi cepet lan alami kanggo mriksa jinis ing Dropbox. Ing pungkasan taun 2016, kita wis duwe kira-kira 420000 baris kode Python kanthi anotasi jinis. Akeh pangguna sing antusias babagan mriksa jinis. Luwih akeh tim pangembangan nggunakake Dropbox mypy.

Kabeh katon apik, nanging isih akeh sing kudu ditindakake. Kita wiwit nindakake survey pangguna internal kanthi periodik kanggo ngenali wilayah masalah proyek lan ngerti masalah apa sing kudu dirampungake dhisik (praktik iki isih digunakake ing perusahaan saiki). Sing paling penting, kaya sing wis jelas, yaiku rong tugas. Kaping pisanan, kita butuh jangkoan jinis kode sing luwih akeh, kaloro, kita butuh mypy supaya bisa luwih cepet. Cetha banget yen karya kita kanggo nyepetake mypy lan ngleksanakake ing proyek perusahaan isih adoh saka rampung. Kita, kanthi ngerti pentinge rong tugas kasebut, mutusake kanggo ngrampungake.

Produktivitas liyane!

Pemeriksaa tambahan nggawe mypy luwih cepet, nanging alat kasebut isih ora cukup cepet. Akeh pemeriksaan tambahan sing suwene kira-kira sak menit. Alesan kanggo iki yaiku impor siklus. Iki mbokmenawa ora bakal kaget sapa wae sing wis nggarap basis kode gedhe sing ditulis ing Python. Kita duwe set atusan modul, sing saben-saben ora langsung ngimpor kabeh liyane. Yen ana file ing loop impor sing diganti, mypy kudu ngolah kabeh file ing loop kasebut, lan asring modul apa wae sing ngimpor modul saka loop kasebut. Siji siklus kasebut yaiku "ketergantungan tangle" sing kondhang sing nyebabake akeh masalah ing Dropbox. Sawise struktur iki ngemot sawetara atus modul, nalika diimpor, langsung utawa ora langsung, akeh tes, uga digunakake ing kode produksi.

We dianggep kamungkinan saka "untangling" dependensi bunder, nanging kita ora duwe sumber daya kanggo nindakaken. Ana akeh banget kode sing ora kita kenal. AkibatΓ©, kita teka karo pendekatan alternatif. Kita mutusake kanggo nggawe mypy bisa cepet sanajan ana "ketergantungan tangles". Kita entuk gol iki nggunakake daemon mypy. Daemon minangka proses server sing ngetrapake rong kemampuan sing menarik. Kaping pisanan, nyimpen informasi babagan kabeh basis kode ing memori. Iki tegese saben sampeyan mbukak mypy, sampeyan ora kudu mbukak data cache sing ana gandhengane karo ewonan dependensi sing diimpor. Kapindho, dheweke kanthi teliti, ing tingkat unit struktural cilik, nganalisa dependensi antarane fungsi lan entitas liyane. Contone, yen fungsi foo nelpon fungsi bar, banjur ana ketergantungan foo saka bar. Nalika file diganti, daemon pisanan, ing isolasi, mung ngolah file sing diganti. Banjur ndeleng owah-owahan sing katon sacara eksternal menyang file kasebut, kayata tandha fungsi sing diganti. Daemon nggunakake informasi rinci babagan impor mung kanggo mriksa maneh fungsi sing bener nggunakake fungsi sing diowahi. Biasane, kanthi pendekatan iki, sampeyan kudu mriksa sawetara fungsi.

Ngleksanakake kabeh iki ora gampang, amarga implementasi mypy asli fokus banget kanggo ngolah file siji-sijine. Kita kudu ngatasi akeh kahanan borderline, kedadeyan sing mbutuhake mriksa bola-bali ing kasus sing ana owah-owahan ing kode kasebut. Contone, iki kedadeyan nalika kelas diwenehi kelas dhasar anyar. Sawise nindakake apa sing dikarepake, kita bisa nyuda wektu eksekusi paling akeh pemeriksaan tambahan dadi sawetara detik. Iki ketoke kaya gedhe kamenangan kanggo kita.

Malah luwih produktivitas!

Bebarengan karo cache remot sing dakkandhakake ing ndhuwur, daemon mypy meh ngrampungake masalah sing muncul nalika programmer kerep mbukak mriksa jinis, nggawe owah-owahan ing sawetara file. Nanging, kinerja sistem ing kasus panggunaan paling apik isih adoh saka optimal. Miwiti mypy sing resik bisa njupuk luwih saka 15 menit. Lan iki luwih akeh tinimbang kita bakal seneng. Saben minggu kahanan dadi luwih elek amarga programer terus nulis kode anyar lan nambah anotasi menyang kode sing wis ana. Pangguna kita isih luwe kanggo kinerja liyane, nanging kita padha seneng ketemu wong setengah.

Kita mutusake bali menyang salah sawijining ide sadurunge babagan mypy. Yaiku, kanggo ngowahi kode Python dadi kode C. Eksperimen karo Cython (sistem sing ngidini sampeyan nerjemahake kode sing ditulis ing Python menyang kode C) ora menehi kacepetan sing katon, mula kita mutusake kanggo nyegerake ide nulis kompiler dhewe. Wiwit basis kode mypy (ditulis ing Python) wis ngemot kabeh anotasi jinis sing dibutuhake, mula kita mikir bakal migunani kanggo nggunakake anotasi kasebut kanggo nyepetake sistem kasebut. Aku cepet nggawe prototipe kanggo nyoba idea iki. Iki nuduhake peningkatan kinerja luwih saka 10 kaping ing macem-macem patokan mikro. Ide kita yaiku kanggo ngumpulake modul Python menyang modul C nggunakake Cython, lan ngowahi anotasi jinis dadi cek jinis run-time (biasane anotasi jinis ora digatekake nalika mbukak-wektu lan mung digunakake dening sistem mriksa jinis). Kita bener ngrancang nerjemahake implementasi mypy saka Python menyang basa sing dirancang kanggo diketik kanthi statis, sing bakal katon (lan, umume, bisa digunakake) kaya Python. (Migrasi lintas-basa kaya iki wis dadi tradisi proyek mypy. Implementasi mypy asli ditulis ing Alore, banjur ana hibrida sintaksis Jawa lan Python).

Fokus ing API ekstensi CPython minangka kunci supaya ora kelangan kemampuan manajemen proyek. Kita ora perlu ngleksanakake mesin virtual utawa perpustakaan sing dibutuhake mypy. Kajaba iku, kita isih bakal duwe akses menyang kabeh ekosistem Python lan kabeh piranti (kayata pytest). Iki tegese kita bisa terus nggunakake kode Python sing diinterpretasikake sajrone pembangunan, supaya kita bisa terus nggarap pola sing cepet banget kanggo nggawe owah-owahan kode lan nguji, tinimbang ngenteni kode kasebut dikompilasi. Iku katon kaya kita padha nindakake proyek gedhe lungguh ing loro kursi, ngandika, lan kita tresna iku.

Compiler, sing diarani mypyc (amarga nggunakake mypy minangka front-end kanggo nganalisa jinis), dadi proyek sing sukses banget. Sakabèhé, kita entuk kacepetan kira-kira 4x kanggo mypy sing kerep mlaku tanpa caching. Ngembangake inti proyek mypyc njupuk tim cilik Michael Sullivan, Ivan Levkivsky, Hugh Hahn, lan aku babagan 4 sasi tanggalan. Jumlah karya iki luwih cilik tinimbang sing dibutuhake kanggo nulis ulang mypy, contone, ing C ++ utawa Go. Lan kita kudu nggawe owah-owahan luwih sithik kanggo proyek kasebut tinimbang sing kudu ditindakake nalika nulis maneh ing basa liya. Kita uga ngarep-arep supaya bisa nggawa mypyc menyang level sing bisa digunakake dening programer Dropbox liyane kanggo ngumpulake lan nyepetake kode kasebut.

Kanggo entuk tingkat kinerja iki, kita kudu ngetrapake sawetara solusi teknik sing menarik. Mangkono, kompiler bisa nyepetake akeh operasi kanthi nggunakake konstruksi C tingkat rendah kanthi cepet. Contone, panggilan fungsi sing dikompilasi diterjemahake dadi panggilan fungsi C. Lan telpon kasebut luwih cepet tinimbang nelpon fungsi sing diinterpretasikake. Sawetara operasi, kayata telusuran kamus, isih melu nggunakake telpon C-API biasa saka CPython, sing mung luwih cepet nalika dikompilasi. Kita bisa ngilangi beban tambahan ing sistem sing digawe kanthi interpretasi, nanging ing kasus iki mung entuk bathi cilik babagan kinerja.

Kanggo ngenali operasi "alon" sing paling umum, kita nindakake profil kode. Bersenjata karo data iki, kita nyoba kanggo salah siji Tweak mypyc supaya bakal generate kode C luwih cepet kanggo operasi kuwi, utawa nulis ulang kode Python cocog nggunakake operasi luwih cepet (lan kadhangkala kita mung ora duwe solusi cukup prasaja kanggo sing utawa masalah liyane) . Nulis ulang kode Python asring dadi solusi sing luwih gampang kanggo masalah kasebut tinimbang duwe kompiler kanthi otomatis nindakake transformasi sing padha. Ing jangka panjang, kita pengin ngotomatisasi akeh transformasi kasebut, nanging ing wektu kasebut kita fokus kanggo nyepetake mypy kanthi minimal gaweyan. Lan ing obah menyang goal iki, kita Cut sawetara sudhut.

Terus ...

Para pamaca ingkang kinurmatan! Apa kesan sampeyan babagan proyek mypy nalika sampeyan ngerti babagan orane?

Path kanggo ngetik 4 yuta baris kode Python. Bagean 2
Path kanggo ngetik 4 yuta baris kode Python. Bagean 2

Source: www.habr.com

Add a comment