ClickCease Los cambios de Python 2 a 3 hacen inevitable la refactorización del código - TuxCare

Únase a nuestro popular boletín

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.

Los cambios de Python 2 a 3 hacen inevitable la refactorización del código

DeShea Witcher

14 de septiembre de 2022 - Vicepresidente de Marketing

Enfrentarse a la perspectiva de tener que profundizar en código antiguo para hacerlo funcionar con una nueva versión del lenguaje es una de las cosas que los desarrolladores intentan evitar a toda costa. Es difícil entender el código antiguo; los cambios inesperados pueden introducir nuevos errores, el rendimiento probablemente se resentirá y supone un esfuerzo tremendo a cambio de muy poco. Al fin y al cabo, no estás añadiendo nada nuevo, sólo haciendo que funcione como antes. Este post cubrirá algunos ejemplos de cambios de Python 2 y 3 que hacen que esta refactorización de código sea inevitable.

Así que tienes tu aplicación Python 2 funcionando tal y como estaba previsto. Lleva unos años funcionando perfectamente, el equipo de desarrollo ha limado todas las asperezas y todo el mundo está contento con su rendimiento. Hace su trabajo y se quita de en medio cuando ya no es necesaria.

Pero, de repente, aparece una nueva vulnerabilidad dirigida a Python 2. Ya no hay parches de seguridad disponibles porque ya no tiene soporte oficial. Los parches de seguridad ya no están disponibles, ya que está fuera de soporte oficial, por lo que su fantástica aplicación, sin tener la culpa, ahora también es vulnerable y se ha convertido en un problema de seguridad para la organización. Siendo el diligente director de TI que eres, encargas a tu equipo de desarrollo que priorice la refactorización del código para que se ejecute con una versión segura de Python 3.

Su equipo tenía otros proyectos entre manos, y todo eso queda ahora en suspenso. Es una decisión costosa, pero hay que hacerlo, ¿no? Lleva unas semanas reunir todos los detalles sobre los cambios de código necesarios y cómo afectan a otras secciones del código inesperadas o que ya no se recuerdan. Una gran parte de la lógica central tiene que ser reescrita, ya que algunas funcionalidades han quedado obsoletas desde Python 2, y la sustitución en Python 3 no es drop-in-place, por lo que también hay que crear nuevas pruebas unitarias.

Pasan otras semanas mientras los desarrolladores se esfuerzan por entender un código mal documentado escrito por un ex colega que ya no trabaja en la organización. Parece que hay algunas secciones de código que "simplemente funcionan", pero ya nadie entiende por qué. Ah, y algunas dependencias no soportan Python 3 y probablemente no lo harán en un futuro próximo - los proyectos parecen ya no estar soportados.

Después de meses de duro trabajo, el equipo de desarrollo vuelve con una nueva versión de la aplicación. Se parece ligeramente a la original; algunas opciones de interfaz de usuario dificultan el uso de los conocimientos acumulados, por lo que es necesario volver a formar a los operadores.

El rendimiento parece verse afectado cada vez que alguien aplica algún cambio a la base de datos. Nadie sabe muy bien por qué, pero una de las dependencias que hubo que escribir desde cero lo solucionaba mejor. Y todos los proyectos iniciales que el equipo tenía entre manos también están ahora retrasados y por encima del presupuesto.

El equipo volvió con algunas de las conclusiones para conservarlas como conocimiento útil para futuros esfuerzos de refactorización:

División:

Python 3: 5/2 == 2,5

Python 2: 5/2 == 2 (la duplicación de "/" a "//" devuelve el comportamiento anterior)

Dividir enteros ahora devuelve un float y ya no es un int.

 

Imprime:

Python 3: print("")

Python 2: imprimir ""

 

Cambios en el diccionario:

Python 3: los métodos dict keys(), items(), values() devuelven vistas

Python 2: estos métodos devuelven listas. Además, los métodos iterkeys(), iteritems e itervalues() ya no son compatibles.

 

Clasificación:

Python 3: cmp() ya no debe utilizarse.

 

Texto y binario:

Los datos de texto y binarios son ahora conceptos diferentes y ya no deben almacenarse en cadenas. Algunas operaciones con cadenas ya no funcionan en datos en los que antes funcionaban porque contienen caracteres que ya no están permitidos en cadenas. 

 

Tuplas:

Los parámetros de tupla ya no se pueden descomprimir como antes.

 

Se han eliminado varias palabras clave:

“<>” is now “!=”.

Los literales enteros ya no funcionan con una l o L de cierre.

Los literales de cadena ya no funcionan con una u o U de cierre.

Importar todo desde un módulo ahora sólo funciona a nivel de módulo, no dentro de una función.

 

Y muchos, muchos otros cambios (La lista completa puede verse aquí: https://docs.python.org/3/whatsnew/3.0.htmlque se utilizó como fuente para este artículo).

Al final del proceso, la aplicación funcionaba peor que antes; no se cosechó ningún beneficio real del paso a un nuevo nivel de lenguaje: sólo se utilizaron construcciones que sustituían a la funcionalidad antigua, y ninguna característica avanzada nueva, ya que el objetivo era simplemente conseguir que volviera a funcionar. Fue una tarea costosa que afectó a muchas otras actividades de la organización y causó trastornos a todos los niveles.

 

¿Qué se podría haber hecho en su lugar?

Existe una alternativa mejor en forma de Extended Lifecycle Support for Python. Al proporcionar correcciones de seguridad oportunas sin introducir cambios a nivel de lenguaje, el problema podría haberse resuelto simplemente desplegando el servicio. El mismo código habría seguido ejecutándose tal cual, se habría corregido la vulnerabilidad de seguridad y se habrían evitado por completo todas las demás interrupciones.

¿Desea ampliar la compatibilidad de su ciclo de vida de productos con Python 2.x?

Hable con un experto en ELS de Python

Conviértete en escritor invitado de TuxCare

Empezar

Correo

Únete a

4,500

Profesionales de Linux y código abierto

Suscríbase a
nuestro boletín