O camiño para verificar 4 millóns de liñas de código Python. Parte 3

Presentámosche á túa atención a terceira parte da tradución de material sobre o camiño que tomou Dropbox ao implementar un sistema de verificación de tipos para código Python.

O camiño para verificar 4 millóns de liñas de código Python. Parte 3

→ Partes anteriores: primeiro и segundo

Acadando 4 millóns de liñas de código escrito

Outro gran desafío (e a segunda preocupación máis común entre os enquisados ​​internamente) foi aumentar a cantidade de código cuberto polas comprobacións de tipo en Dropbox. Probamos varios enfoques para resolver este problema, desde o aumento natural do tamaño da base de código escrito ata o foco dos esforzos do equipo mypy na inferencia de tipos automatizadas estáticas e dinámicas. Ao final, parecía que non había unha estratexia gañadora sinxela, pero puidemos conseguir un rápido crecemento no volume de código anotado combinando moitos enfoques.

Como resultado, o noso maior repositorio de Python (con código de fondo) ten case 4 millóns de liñas de código anotado. O traballo sobre a tipificación de código estático completouse en aproximadamente tres anos. Mypy agora admite varios tipos de informes de cobertura de código que facilitan o seguimento do progreso da escritura. En particular, podemos xerar informes sobre código con ambigüidades nos tipos, como, por exemplo, o uso explícito dun tipo Any en anotacións que non se poden verificar ou con cousas como importar bibliotecas de terceiros que non teñan anotacións de tipo. Como parte dun proxecto para mellorar a precisión da comprobación de tipos en Dropbox, contribuímos a mellorar as definicións de tipos (os chamados ficheiros stub) para algunhas bibliotecas populares de código aberto nun repositorio centralizado de Python mecanografado.

Implementamos (e estandarizamos en PEPs posteriores) novas características do sistema de tipos que permiten tipos máis precisos para algúns patróns específicos de Python. Un exemplo notable disto é TypeDict, que proporciona tipos para dicionarios tipo JSON que teñen un conxunto fixo de claves de cadea, cada un cun valor do seu propio tipo. Seguiremos ampliando o sistema de tipos. O noso seguinte paso probablemente sexa mellorar o soporte para as capacidades numéricas de Python.

O camiño para verificar 4 millóns de liñas de código Python. Parte 3
Número de liñas de código anotado: servidor

O camiño para verificar 4 millóns de liñas de código Python. Parte 3
Número de liñas de código anotado: cliente

O camiño para verificar 4 millóns de liñas de código Python. Parte 3
Número total de liñas de código anotado

Aquí tes unha visión xeral das principais características das cousas que fixemos para aumentar a cantidade de código anotado en Dropbox:

Rigor da anotación. Aumentamos gradualmente os requisitos para o rigor de anotar código novo. Comezamos con consellos de linter que suxerían engadir anotacións aos ficheiros que xa tiñan algunhas anotacións. Agora esiximos anotacións de tipo nos novos ficheiros de Python e na maioría dos ficheiros existentes.

Mecanografía de informes. Enviamos aos equipos informes semanais sobre o nivel de tecleo do seu código e dámoslle consellos sobre o que se debe anotar primeiro.

Popularización de mypy. Falamos de mypy nos eventos e falamos cos equipos para axudarlles a comezar coas anotacións de tipo.

Enquisas. Realizamos enquisas periódicas aos usuarios para identificar os principais problemas. Estamos preparados para ir bastante lonxe na resolución destes problemas (incluso creando un novo idioma para acelerar mypy!).

Rendemento. Melloramos moito o rendemento de mypy usando o daemon e mypyc. Isto fíxose para suavizar os inconvenientes que xorden durante o proceso de anotación e para poder traballar con grandes cantidades de código.

Integración con editores. Creamos ferramentas para permitir a execución de mypy en editores populares en Dropbox. Isto inclúe PyCharm, Vim e VS Code. Isto simplificou moito o proceso de anotación do código e comprobación da súa funcionalidade. Este tipo de accións son habituais cando se anota o código existente.

Análise estática. Creamos unha ferramenta para inferir sinaturas de funcións mediante ferramentas de análise estática. Esta ferramenta só pode funcionar en situacións relativamente sinxelas, pero axudounos a aumentar a nosa cobertura de tipos de código sen moito esforzo.

Soporte para bibliotecas de terceiros. Moitos dos nosos proxectos usan o kit de ferramentas SQLAlchemy. Aproveita as capacidades dinámicas de Python que os tipos PEP 484 non poden modelar directamente. Nós, de acordo co PEP 561, creamos o ficheiro stub correspondente e escribimos un complemento para mypy (código aberto), que mellora o soporte de SQLAlchemy.

Dificultades que atopamos

O camiño cara a 4 millóns de liñas de código escrito non sempre foi doado para nós. Neste camiño atopamos moitos baches e cometemos varios erros. Estes son algúns dos problemas que atopamos. Agardamos que contar sobre eles axude a outros a evitar problemas similares.

Faltan ficheiros. Comezamos o noso traballo comprobando só unha pequena cantidade de ficheiros. Non se comprobou o que non se inclúe nestes ficheiros. Os ficheiros engadíronse á lista de dixitalización cando apareceron neles as primeiras anotacións. Se se importou algo desde un módulo situado fóra do ámbito de verificación, falamos de traballar con valores como Any, que non foron probados en absoluto. Isto levou a unha importante perda de precisión de escritura, especialmente nas primeiras etapas da migración. Este enfoque funcionou sorprendentemente ben ata agora, aínda que unha situación típica é que engadir ficheiros ao alcance da revisión revela problemas noutras partes do código base. No peor dos casos, cando se fusionaron dúas áreas illadas de código, nas que, independentemente entre si, os tipos xa estaban verificados, resultou que os tipos destas áreas eran incompatibles entre si. Isto levou á necesidade de facer moitos cambios nas anotacións. Mirando cara atrás agora, dámonos conta de que deberíamos engadir antes os módulos básicos da biblioteca á área de verificación de tipos de mypy. Isto faría que o noso traballo sexa moito máis previsible.

Anotando código antigo. Cando comezamos, tiñamos preto de 4 millóns de liñas de código Python existente. Estaba claro que anotar todo este código non era unha tarefa fácil. Creamos unha ferramenta chamada PyAnnotate que pode recoller información de tipos mentres se realizan as probas e pode engadir anotacións de tipo ao teu código en función da información recollida. Non obstante, non observamos unha adopción especialmente xeneralizada desta ferramenta. A recollida de información de tipo foi lenta e as anotacións xeradas automaticamente requirían moitas veces moitas edicións manuais. Pensamos en executar esta ferramenta automaticamente cada vez que revisamos o código ou en recompilar información de tipo baseada na análise dun pequeno volume de solicitudes de rede reais, pero decidimos non facelo porque calquera dos dous enfoques era demasiado arriscado.

Como resultado, pódese observar que a maior parte do código foi anotado manualmente polos seus propietarios. Para guiar este proceso na dirección correcta, elaboramos informes sobre módulos e funcións especialmente importantes que deben ser anotados. Por exemplo, é importante proporcionar anotacións de tipo para un módulo da biblioteca que se usa en centos de lugares. Pero un servizo antigo que está a ser substituído por un novo xa non é tan importante para anotar. Tamén estamos experimentando co uso da análise estática para xerar anotacións de tipos para o código heredado.

Importacións cíclicas. Arriba, falei sobre as importacións cíclicas (os "enredos de dependencia"), cuxa existencia dificultaba a aceleración de mypy. Tamén tivemos que traballar duro para que mypy admita todo tipo de modismos que son causados ​​por estas importacións cíclicas. Recentemente completamos un importante proxecto de redeseño do sistema que solucionou a maioría dos problemas de mypy relativos ás importacións circulares. Estes problemas xurdiron en realidade dos primeiros días do proxecto, de volta de Alore, a linguaxe educativa na que se centrou orixinalmente o proxecto mypy. A sintaxe de Alore facilita a resolución de problemas cos comandos de importación cíclica. Mypy moderno herdou algunhas limitacións da súa implementación anterior e sinxela (que era unha boa opción para Alore). Python dificulta traballar con importacións circulares, principalmente porque as expresións son ambiguas. Por exemplo, unha operación de asignación pode definir un alias de tipo. Mypy non sempre é capaz de detectar cousas como esta ata que se procese a maior parte do bucle de importación. Non había tales ambigüidades en Alore. As malas decisións tomadas nas primeiras fases do desenvolvemento do sistema poden presentar unha sorpresa desagradable para o programador moitos anos despois.

Resultados: o camiño cara a 5 millóns de liñas de código e novos horizontes

O proxecto mypy percorreu un longo camiño: desde os primeiros prototipos ata un sistema que controla 4 millóns de liñas de tipos de código de produción. A medida que mypy evolucionou, as suxestións de tipo de Python foron estandarizadas. Nestes días, desenvolveuse un poderoso ecosistema arredor da escritura de código Python. Ten un lugar para o soporte da biblioteca, contén ferramentas auxiliares para IDEs e editores, ten varios sistemas de control de tipos, cada un dos cales ten os seus pros e contras.

Aínda que a verificación de tipos xa é un feito en Dropbox, creo que aínda estamos nos primeiros días de escribir código Python. Creo que as tecnoloxías de verificación de tipos seguirán evolucionando e mellorando.

Se aínda non utilizaches a verificación de tipos no teu proxecto de Python a gran escala, sabe que agora é un bo momento para comezar a pasar á escritura estática. Falei con aqueles que fixeron unha transición semellante. Ningún deles se arrepentiu. A comprobación de tipos fai que Python sexa unha linguaxe moito máis axeitada para desenvolver proxectos grandes que "Python normal".

Queridos lectores! Usas a verificación de tipos nos teus proxectos Python?

O camiño para verificar 4 millóns de liñas de código Python. Parte 3
O camiño para verificar 4 millóns de liñas de código Python. Parte 3

Fonte: www.habr.com

Engadir un comentario