4 million satr Python kodini terishni tekshirish yo'li. 1-qism

Bugun biz sizning e'tiboringizga Dropbox Python kodini boshqarish bilan qanday shug'ullanishi haqidagi material tarjimasining birinchi qismini taqdim etamiz.

4 million satr Python kodini terishni tekshirish yo'li. 1-qism

Dropbox Pythonda ko'p yozadi. Bu biz backend xizmatlari uchun ham, ish stoli mijoz ilovalari uchun ham juda keng foydalaniladigan tildir. Biz ham Go, TypeScript va Rust-dan ko'p foydalanamiz, lekin Python bizning asosiy tilimizdir. Bizning miqyosimizni hisobga olsak va biz Python kodining millionlab satrlari haqida gapiramiz, bunday kodni dinamik ravishda yozish uni tushunishni keraksiz ravishda murakkablashtirgani va mehnat unumdorligiga jiddiy ta'sir qila boshlaganligi ma'lum bo'ldi. Ushbu muammoni yumshatish uchun biz asta-sekin kodimizni mypy yordamida statik turdagi tekshirishga o'tkazishni boshladik. Bu, ehtimol, Python uchun eng mashhur mustaqil turdagi tekshirish tizimidir. Mypy ochiq kodli loyiha bo'lib, uning asosiy ishlab chiquvchilari Dropbox-da ishlaydi.

Dropbox ushbu miqyosda Python kodida statik turdagi tekshirishni amalga oshirgan birinchi kompaniyalardan biri edi. Mypy bugungi kunda minglab loyihalarda qo'llaniladi. Ushbu vosita son-sanoqsiz marta, ular aytganidek, "jangda sinovdan o'tgan". Biz hozir bo'lgan joyga borish uchun uzoq yo'lni bosib o'tdik. Yo'lda ko'plab muvaffaqiyatsiz tashabbuslar va muvaffaqiyatsiz tajribalar bo'ldi. Ushbu post Python-da statik tipni tekshirish tarixini, uning tadqiqot loyihamning bir qismi sifatidagi tosh boshlanishidan boshlab, Python-da yozadigan son-sanoqsiz ishlab chiquvchilar uchun tipni tekshirish va turga ishora qilish odatiy holga aylangan hozirgi kungacha bo'lgan tarixini qamrab oladi. Ushbu mexanizmlar endi IDE va ​​kod analizatorlari kabi ko'plab vositalar tomonidan qo'llab-quvvatlanadi.

Ikkinchi qismni o'qing

Turni tekshirish nima uchun kerak?

Agar siz dinamik ravishda terilgan Python-dan foydalangan bo'lsangiz, so'nggi paytlarda statik yozish va mypy haqida nima uchun bunday shov-shuv bo'layotgani haqida chalkashliklarga duch kelishingiz mumkin. Yoki siz Python-ni dinamik yozish tufayli yoqtirasiz va nima sodir bo'layotgani sizni xafa qiladi. Statik yozish qiymatining kaliti bu yechimlar miqyosi: loyihangiz qanchalik katta bo'lsa, siz statik yozishga shunchalik moyil bo'lasiz va oxir-oqibat, sizga shunchalik ko'p kerak bo'ladi.

Aytaylik, ma'lum bir loyiha o'n minglab qatorlar hajmiga yetdi va u ustida bir nechta dasturchilar ishlayotgani ma'lum bo'ldi. Bizning tajribamizga asoslanib, shunga o'xshash loyihani ko'rib chiqsak, uning kodini tushunish ishlab chiquvchilarni samarali saqlashning kaliti bo'ladi, deb aytishimiz mumkin. Turi izohlarisiz, masalan, funktsiyaga qanday argumentlarni o'tkazish kerakligini yoki funksiya qanday turlarni qaytarishi mumkinligini aniqlash qiyin bo'lishi mumkin. Bu erda odatda turdagi izohlardan foydalanmasdan javob berish qiyin bo'lgan odatiy savollar:

  • Bu funksiya qaytishi mumkinmi? None?
  • Bu dalil nima bo'lishi kerak? items?
  • Atribut turi nima id: int shundaymi, str, yoki, ehtimol, ba'zi maxsus turdagi?
  • Bu dalil ro'yxat bo'lishi kerakmi? Unga kortejni o'tkazish mumkinmi?

Agar siz quyidagi turdagi izohli kod parchasini ko'rib chiqsangiz va shunga o'xshash savollarga javob berishga harakat qilsangiz, bu eng oddiy vazifa ekanligi ayon bo'ladi:

class Resource:
    id: bytes
    ...
    def read_metadata(self, 
                      items: Sequence[str]) -> Dict[str, MetadataItem]:
        ...

  • read_metadata qaytmaydi None, chunki qaytish turi emas Optional[…].
  • dalil items qatorlar ketma-ketligidir. Uni tasodifiy takrorlash mumkin emas.
  • Xususiyat id baytlar qatoridir.

Ideal dunyoda barcha bunday nozikliklar o'rnatilgan hujjatlarda (docstring) tasvirlangan bo'lishini kutish mumkin. Ammo tajriba bunday hujjatlar ko'pincha siz ishlashingiz kerak bo'lgan kodda kuzatilmasligiga juda ko'p misollar keltiradi. Kodeksda bunday hujjatlar mavjud bo'lsa ham, uning mutlaq to'g'riligiga ishonish mumkin emas. Ushbu hujjatlar noaniq, noto'g'ri va tushunmovchiliklarga ochiq bo'lishi mumkin. Katta jamoalarda yoki yirik loyihalarda bu muammo juda keskin bo'lishi mumkin.

Python loyihalarning dastlabki yoki oraliq bosqichlarida ustun bo'lsa-da, bir nuqtada muvaffaqiyatli loyihalar va Python-dan foydalanadigan kompaniyalar hayotiy savolga duch kelishi mumkin: "Biz hamma narsani statik tarzda yozilgan tilda qayta yozishimiz kerakmi?".

Mypy kabi tiplarni tekshirish tizimlari yuqoridagi muammoni ishlab chiquvchiga turlarni tavsiflash uchun rasmiy til bilan ta'minlash va turdagi deklaratsiyalar dasturni amalga oshirishga mos kelishini tekshirish (va ixtiyoriy ravishda ularning mavjudligini tekshirish) orqali hal qiladi. Umuman olganda, shuni aytishimiz mumkinki, ushbu tizimlar bizning ixtiyorimizga diqqat bilan tekshirilgan hujjatlar kabi narsalarni qo'yadi.

Bunday tizimlardan foydalanish boshqa afzalliklarga ega va ular allaqachon mutlaqo ahamiyatsiz:

  • Turni tekshirish tizimi ba'zi kichik (va unchalik kichik bo'lmagan) xatolarni aniqlay oladi. Oddiy misol, ular qiymatni qayta ishlashni unutganlarida None yoki boshqa maxsus shart.
  • Kodni qayta ishlash juda soddalashtirilgan, chunki turni tekshirish tizimi qaysi kodni o'zgartirish kerakligi haqida juda aniq. Shu bilan birga, testlar bilan kodning 100% qoplanishiga umid qilishning hojati yo'q, bu har qanday holatda ham odatda amalga oshirilmaydi. Muammoning sababini aniqlash uchun biz stek izining chuqurligini o'rganishimiz shart emas.
  • Hatto yirik loyihalarda ham mypy ko'pincha soniyaning bir qismida to'liq turdagi tekshiruvni amalga oshirishi mumkin. Va testlarning bajarilishi odatda o'nlab soniyalar yoki hatto daqiqalarni oladi. Turni tekshirish tizimi dasturchiga zudlik bilan fikr-mulohaza bildiradi va unga o‘z ishini tezroq bajarish imkonini beradi. Kod testi natijalarini tezroq olish uchun endi u haqiqiy ob'ektlarni masxara va yamoqlar bilan almashtiradigan nozik va texnik xizmat ko'rsatish qiyin bo'lgan birlik testlarini yozishi shart emas.

PyCharm yoki Visual Studio Code kabi IDE va ​​muharrirlar ishlab chiquvchilarga kodni to'ldirish, xatolarni ajratib ko'rsatish va tez-tez ishlatiladigan til konstruksiyalarini qo'llab-quvvatlash uchun turdagi izohlar kuchidan foydalanadi. Va bular matn terishning ba'zi afzalliklari. Ba'zi dasturchilar uchun bularning barchasi matn terish foydasiga asosiy dalildir. Bu amalga oshirilgandan so'ng darhol foyda keltiradigan narsa. Turlar uchun ushbu foydalanish holati mypy kabi alohida turdagi tekshirish tizimini talab qilmaydi, ammo shuni ta'kidlash kerakki, mypy turdagi izohlarni kod bilan mos saqlashga yordam beradi.

Mypy foni

Mypy tarixi Buyuk Britaniyada, Kembrijda, men Dropbox-ga qo'shilishimdan bir necha yil oldin boshlangan. Men doktorlik tadqiqotimning bir qismi sifatida statik tiplangan va dinamik tillarni birlashtirishda ishtirok etdim. Menga Jeremi Siek va Valid Tahaning bosqichma-bosqich yozish haqidagi maqolasi va Typed Racket loyihasi ilhom berdi. Men turli loyihalar uchun bir xil dasturlash tilidan foydalanish yo'llarini topishga harakat qildim - kichik skriptlardan tortib millionlab satrlardan iborat kod bazalarigacha. Shu bilan birga, men har qanday miqyosdagi loyihada juda katta murosaga kelish shart emasligini ta'minlashni xohlardim. Bularning barchasining muhim qismi toifalanmagan prototip loyihasidan har tomonlama sinovdan o'tgan statik tipdagi tayyor mahsulotga bosqichma-bosqich o'tish g'oyasi edi. Hozirgi kunda bu g'oyalar asosan tabiiy deb qabul qilinadi, ammo 2010 yilda bu hali ham faol o'rganilayotgan muammo edi.

Turni tekshirish bo'yicha mening asl ishim Pythonga qaratilgan emas edi. Buning o'rniga men kichik "uy qurilishi" tilidan foydalandim Alore. Mana sizga nima haqida gapirayotganimizni tushunishga imkon beradigan misol (bu yerda turdagi izohlar ixtiyoriy):

def Fib(n as Int) as Int
  if n <= 1
    return n
  else
    return Fib(n - 1) + Fib(n - 2)
  end
end

Soddalashtirilgan ona tilidan foydalanish ilmiy tadqiqotlarda qo'llaniladigan keng tarqalgan yondashuvdir. Bu shuni anglatadiki, bu sizga tezda tajriba o'tkazishga imkon beradi, shuningdek, tadqiqotga hech qanday aloqasi bo'lmagan narsalarni osongina e'tiborsiz qoldirishi mumkin. Haqiqiy dunyo dasturlash tillari keng ko'lamli hodisalar bo'lib, murakkab ilovalarga ega va bu tajribani sekinlashtiradi. Biroq, soddalashtirilgan tilga asoslangan har qanday natijalar biroz shubhali ko'rinadi, chunki bu natijalarni olishda tadqiqotchi tillardan amaliy foydalanish uchun muhim bo'lgan fikrlarni qurbon qilgan bo'lishi mumkin.

Mening Alore uchun turdagi tekshiruvchim juda istiqbolli ko'rinardi, lekin men uni haqiqiy kod bilan sinab ko'rish orqali sinab ko'rmoqchi edim, siz aytishingiz mumkinki, Aloreda yozilmagan. Yaxshiyamki, men uchun Alore tili asosan Python bilan bir xil g'oyalarga asoslangan edi. Python sintaksisi va semantikasi bilan ishlashi uchun matn terish moslamasini qayta tiklash juda oson edi. Bu bizga ochiq kodli Python kodida turdagi tekshirishni sinab ko'rish imkonini berdi. Bundan tashqari, men Alore-da yozilgan kodni Python kodiga aylantirish uchun transpiler yozdim va undan matn terish kodini tarjima qilish uchun foydalandim. Endi menda Python-da yozilgan turdagi tekshirish tizimi bor edi, u Python-ning quyi to'plamini, shu tilning bir turini qo'llab-quvvatlaydi! (Alore uchun mantiqiy bo'lgan ba'zi arxitektura qarorlari Python uchun juda mos emas edi va bu hali ham mypy kod bazasining qismlarida seziladi.)

Aslida, mening tip tizimim tomonidan qo'llab-quvvatlanadigan tilni hozircha Python deb atash mumkin emas: bu Python 3 tipidagi annotatsiya sintaksisining ba'zi cheklovlari tufayli Pythonning bir varianti edi.

Bu Java va Python aralashmasiga o'xshardi:

int fib(int n):
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

O'sha paytdagi g'oyalarimdan biri Python-ni C ga yoki JVM bayt-kodiga kompilyatsiya qilish orqali ishlashni yaxshilash uchun turdagi izohlardan foydalanish edi. Men kompilyator prototipini yozish bosqichiga keldim, lekin men bu fikrdan voz kechdim, chunki tipni tekshirishning o'zi juda foydali ko'rinardi.

Men o'z loyihamni Santa Klaradagi PyCon 2013 ko'rgazmasida taqdim etdim. Men bu haqda umrbod xayrixoh Python diktatori Guido van Rossum bilan ham gaplashdim. U meni o‘z sintaksisimni tashlab, standart Python 3 sintaksisiga rioya qilishga ishontirdi. Python 3 funksiya izohlarini qo‘llab-quvvatlaydi, shuning uchun mening misolimni quyida ko‘rsatilganidek qayta yozish mumkin, natijada oddiy Python dasturi paydo bo‘ladi:

def fib(n: int) -> int:
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Men ba'zi murosaga kelishga majbur bo'ldim (birinchi navbatda, men o'zimning sintaksisimni aynan shu sababli ixtiro qilganimni ta'kidlamoqchiman). Xususan, o‘sha paytdagi tilning eng so‘nggi versiyasi bo‘lgan Python 3.3 o‘zgaruvchan izohlarni qo‘llab-quvvatlamagan. Men Guido bilan elektron pochta orqali bunday izohlarning sintaktik dizayni uchun turli xil imkoniyatlarni muhokama qildim. Biz o'zgaruvchilar uchun turdagi sharhlardan foydalanishga qaror qildik. Bu mo'ljallangan maqsadga xizmat qildi, lekin biroz og'ir edi (Python 3.6 bizga yaxshi sintaksisni berdi):

products = []  # type: List[str]  # Eww

Izohlarni yozish Python 2-ni qo'llab-quvvatlash uchun ham foydali bo'ldi, bu esa turdagi izohlarni qo'llab-quvvatlamaydi:

f fib(n):
    # type: (int) -> int
    if n <= 1:
        return n
    else:
        return fib(n - 1) + fib(n - 2)

Ma’lum bo‘lishicha, bu (va boshqa) o‘zaro kelishuvlarning ahamiyati yo‘q – statik yozishning afzalliklari foydalanuvchilar tez orada ideal bo‘lmagan sintaksisni unutib qo‘yishgan. Turi tekshirilgan Python kodida maxsus sintaktik konstruksiyalardan foydalanilmaganligi sababli mavjud Python vositalari va kodni qayta ishlash jarayonlari normal ishlashda davom etdi, bu esa ishlab chiquvchilarga yangi vositani o‘rganishni ancha osonlashtirdi.

Gido, shuningdek, bitiruv dissertatsiyasini tugatganimdan keyin meni Dropbox-ga qo'shilishga ko'ndirdi. Mypy hikoyasining eng qiziqarli qismi shu erda boshlanadi.

Davomi bor…

Hurmatli o'quvchilar! Agar siz Python-dan foydalansangiz, ushbu tilda ishlab chiqayotgan loyihalaringiz miqyosi haqida bizga xabar bering.

4 million satr Python kodini terishni tekshirish yo'li. 1-qism
4 million satr Python kodini terishni tekshirish yo'li. 1-qism

Manba: www.habr.com

a Izoh qo'shish