Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3

Kami membentangkan kepada perhatian anda bahagian ketiga terjemahan bahan tentang laluan yang diambil oleh Dropbox semasa melaksanakan sistem semakan jenis untuk kod Python.

Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3

β†’ Bahagian sebelumnya: pertama ΠΈ kedua

Mencapai 4 juta baris kod yang ditaip

Satu lagi cabaran utama (dan kebimbangan kedua paling biasa di kalangan mereka yang ditinjau secara dalaman) ialah meningkatkan jumlah kod yang dilindungi oleh semakan jenis dalam Dropbox. Kami telah mencuba beberapa pendekatan untuk menyelesaikan masalah ini, daripada membesarkan saiz pangkalan kod ditaip secara semula jadi kepada memfokuskan usaha pasukan mypy pada inferens jenis automatik statik dan dinamik. Akhirnya, nampaknya tidak ada strategi kemenangan yang mudah, tetapi kami dapat mencapai pertumbuhan pesat dalam jumlah kod beranotasi dengan menggabungkan banyak pendekatan.

Akibatnya, repositori Python terbesar kami (dengan kod belakang) mempunyai hampir 4 juta baris kod beranotasi. Kerja-kerja menaip kod statik telah disiapkan dalam masa lebih kurang tiga tahun. Mypy kini menyokong pelbagai jenis laporan liputan kod yang memudahkan untuk memantau kemajuan menaip. Khususnya, kami boleh menjana laporan tentang kod dengan kesamaran jenis, seperti, contohnya, penggunaan jenis yang jelas. Any dalam anotasi yang tidak boleh disahkan atau dengan perkara seperti mengimport perpustakaan pihak ketiga yang tidak mempunyai anotasi jenis. Sebagai sebahagian daripada projek untuk meningkatkan ketepatan penyemakan jenis dalam Dropbox, kami menyumbang untuk menambah baik takrif jenis (yang dipanggil fail rintisan) untuk beberapa perpustakaan sumber terbuka yang popular dalam repositori Python terpusat. ditaip.

Kami melaksanakan (dan menyeragamkan dalam PEP seterusnya) ciri baharu sistem jenis yang membenarkan jenis yang lebih tepat untuk beberapa corak Python tertentu. Satu contoh yang ketara ialah TypeDict, yang menyediakan jenis untuk kamus seperti JSON yang mempunyai set kunci rentetan tetap, setiap satu dengan nilai jenisnya sendiri. Kami akan terus mengembangkan sistem jenis. Langkah seterusnya kami mungkin akan meningkatkan sokongan untuk keupayaan berangka Python.

Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3
Bilangan baris kod beranotasi: pelayan

Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3
Bilangan baris kod beranotasi: klien

Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3
Jumlah bilangan baris kod beranotasi

Berikut ialah gambaran keseluruhan ciri utama perkara yang kami lakukan untuk meningkatkan jumlah kod beranotasi dalam Dropbox:

Ketegasan anotasi. Kami secara beransur-ansur meningkatkan keperluan untuk ketegasan menganotasi kod baharu. Kami bermula dengan petua linter yang mencadangkan penambahan anotasi pada fail yang sudah mempunyai beberapa anotasi. Kami kini memerlukan anotasi jenis dalam fail Python baharu dan dalam kebanyakan fail sedia ada.

Menaip laporan. Kami menghantar laporan mingguan pasukan tentang tahap menaip dalam kod mereka dan memberi nasihat tentang perkara yang perlu diberi anotasi terlebih dahulu.

Mempopularkan mypy. Kami bercakap tentang mypy di acara dan bercakap dengan pasukan untuk membantu mereka bermula dengan anotasi jenis.

Undian. Kami menjalankan tinjauan pengguna secara berkala untuk mengenal pasti masalah utama. Kami bersedia untuk pergi agak jauh dalam menyelesaikan masalah ini (malah mencipta bahasa baharu untuk mempercepatkan mypy!).

Prestasi. Kami telah meningkatkan prestasi mypy dengan menggunakan daemon dan mypyc. Ini dilakukan untuk melicinkan kesulitan yang timbul semasa proses anotasi, dan agar dapat berfungsi dengan jumlah kod yang banyak.

Integrasi dengan editor. Kami telah membina alatan untuk menyokong menjalankan mypy dalam editor yang popular di Dropbox. Ini termasuk PyCharm, Vim dan Kod VS. Ini sangat memudahkan proses menganotasi kod dan menyemak fungsinya. Jenis tindakan ini adalah perkara biasa apabila menganotasi kod sedia ada.

Analisis statik. Kami mencipta alat untuk membuat kesimpulan tandatangan fungsi menggunakan alat analisis statik. Alat ini hanya boleh berfungsi dalam situasi yang agak mudah, tetapi ia membantu kami meningkatkan liputan jenis kod kami tanpa banyak usaha.

Sokongan untuk perpustakaan pihak ketiga. Banyak projek kami menggunakan kit alat SQLAlchemy. Ia mengambil kesempatan daripada keupayaan dinamik Python yang jenis PEP 484 tidak dapat dimodelkan secara langsung. Kami, mengikut PEP 561, mencipta fail rintisan yang sepadan dan menulis pemalam untuk mypy (sumber terbuka), yang meningkatkan sokongan SQLAlchemy.

Kesukaran yang kami hadapi

Laluan ke 4 juta baris kod yang ditaip tidak selalu mudah untuk kami. Di laluan ini kami menemui banyak jalan berlubang dan melakukan beberapa kesilapan. Ini antara masalah yang kami hadapi. Kami berharap bahawa memberitahu tentang mereka akan membantu orang lain mengelakkan masalah yang sama.

fail hilang. Kami memulakan kerja kami dengan menyemak hanya sejumlah kecil fail. Apa-apa yang tidak termasuk dalam fail ini tidak disemak. Fail telah ditambahkan pada senarai imbasan apabila anotasi pertama muncul di dalamnya. Jika sesuatu telah diimport daripada modul yang terletak di luar skop pengesahan, maka kami bercakap tentang bekerja dengan nilai seperti Any, yang tidak diuji sama sekali. Ini menyebabkan kehilangan ketepatan menaip yang ketara, terutamanya pada peringkat awal penghijrahan. Pendekatan ini telah berfungsi dengan baik setakat ini, walaupun situasi biasa ialah penambahan fail pada skop semakan mendedahkan masalah di bahagian lain pangkalan kod. Dalam kes yang paling teruk, apabila dua kawasan terpencil kod digabungkan, di mana, secara berasingan antara satu sama lain, jenis telah diperiksa, ternyata jenis kawasan ini tidak serasi antara satu sama lain. Ini menyebabkan keperluan untuk membuat banyak perubahan pada anotasi. Mengimbas kembali sekarang, kami menyedari bahawa kami sepatutnya menambah modul perpustakaan teras ke kawasan semakan jenis mypy lebih awal. Ini akan menjadikan kerja kami lebih mudah diramal.

Menganotasi kod lama. Apabila kami mula, kami mempunyai kira-kira 4 juta baris kod Python sedia ada. Jelas sekali bahawa menganotasi semua kod ini bukanlah tugas yang mudah. Kami telah mencipta alat yang dipanggil PyAnnotate yang boleh mengumpul maklumat jenis semasa ujian dijalankan dan boleh menambah anotasi jenis pada kod anda berdasarkan maklumat yang dikumpul. Walau bagaimanapun, kami tidak menyedari penggunaan alat ini secara meluas. Maklumat jenis pengumpulan adalah perlahan, dan anotasi yang dijana secara automatik selalunya memerlukan banyak pengeditan manual. Kami berfikir tentang menjalankan alat ini secara automatik setiap kali kami menyemak kod, atau mengumpul maklumat jenis berdasarkan menganalisis beberapa jumlah kecil permintaan rangkaian sebenar, tetapi memutuskan untuk tidak melakukannya kerana kedua-dua pendekatan adalah terlalu berisiko.

Akibatnya, boleh diperhatikan bahawa kebanyakan kod telah dijelaskan secara manual oleh pemiliknya. Untuk membimbing proses ini ke arah yang betul, kami menyediakan laporan tentang modul dan fungsi penting yang perlu diberi anotasi. Sebagai contoh, adalah penting untuk menyediakan anotasi jenis untuk modul perpustakaan yang digunakan di ratusan tempat. Tetapi perkhidmatan lama yang digantikan dengan perkhidmatan baharu tidak lagi begitu penting untuk dianotasi. Kami juga sedang bereksperimen dengan menggunakan analisis statik untuk menjana anotasi jenis untuk kod warisan.

Import kitaran. Di atas, saya bercakap tentang import kitaran ("kekusutan pergantungan"), yang kewujudannya menyukarkan untuk mempercepatkan mypy. Kami juga terpaksa bekerja keras untuk menjadikan mypy menyokong semua jenis simpulan bahasa yang disebabkan oleh import kitaran ini. Kami baru-baru ini menyelesaikan projek reka bentuk semula sistem utama yang membetulkan kebanyakan isu mypy berkenaan import pekeliling. Masalah ini sebenarnya berpunca daripada hari-hari awal projek, kembali dari Alore, bahasa pendidikan yang pada asalnya difokuskan oleh projek mypy. Sintaks Alore memudahkan untuk menyelesaikan masalah dengan arahan import kitaran. Mypy moden telah mewarisi beberapa batasan daripada pelaksanaannya yang lebih awal dan berfikiran mudah (yang sangat sesuai untuk Alore). Python membuat kerja dengan import bulat sukar, terutamanya kerana ungkapan tidak jelas. Sebagai contoh, operasi tugasan sebenarnya boleh menentukan alias jenis. Mypy tidak selalu dapat mengesan perkara seperti ini sehingga kebanyakan gelung import telah diproses. Tiada kekaburan seperti itu di Alore. Keputusan buruk yang dibuat pada peringkat awal pembangunan sistem boleh memberikan kejutan yang tidak menyenangkan kepada pengaturcara bertahun-tahun kemudian.

Keputusan: laluan ke 5 juta baris kod dan ufuk baharu

Projek mypy telah berjalan jauh - daripada prototaip awal kepada sistem yang mengawal 4 juta baris jenis kod pengeluaran. Apabila mypy berkembang, pembayang jenis Python telah diseragamkan. Hari ini, ekosistem yang berkuasa telah dibangunkan di sekitar menaip kod Python. Ia mempunyai tempat untuk sokongan perpustakaan, ia mengandungi alat tambahan untuk IDE dan editor, ia mempunyai beberapa jenis sistem kawalan, yang masing-masing mempunyai kebaikan dan keburukan sendiri.

Walaupun semakan jenis sudah diberikan di Dropbox, saya percaya kita masih di peringkat awal menaip kod Python. Saya fikir teknologi semakan jenis akan terus berkembang dan bertambah baik.

Jika anda belum lagi menggunakan semakan jenis dalam projek Python berskala besar anda, maka ketahuilah bahawa sekarang adalah masa yang sangat baik untuk mula beralih kepada menaip statik. Saya telah bercakap dengan mereka yang telah membuat peralihan yang sama. Tiada seorang pun daripada mereka yang menyesalinya. Pemeriksaan jenis menjadikan Python bahasa yang lebih sesuai untuk membangunkan projek besar daripada "Pyton biasa."

Pembaca yang dihormati! Adakah anda menggunakan semakan jenis dalam projek Python anda?

Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3
Laluan untuk menyemak taip 4 juta baris kod Python. Bahagian 3

Sumber: www.habr.com

Tambah komen