lunes, 28 de marzo de 2011

Características de Python 2.7 obsoletas en 3.x



Una reciente discusión en python-dev
puso de manifiesto un fallo en la actual política de obsolescencia (deprecation)
adoptada por los desarrolladores en la migración de 2.7 a la nueva 3.x.
En consecuencia, el equipo de desarrollo ha tenido que modificar su
política para tener en cuenta que los usuarios migrarán directamente de Python 2.7
a la última versión de 3.x, sin pasar por versiones intermedias.


Antecedentes


Python tiene un fuerte compromiso con la compatibilidad con versiones anteriores.
No se permite ningún cambio a menos que esté de acuerdo con las directrices de compatibilidad,
que en esencia dicen que programas correctos no deben fallar en versiones más modernas.
Sin embargo, esto no es siempre posible, por ejemplo, cuando una API deja de funcionar y debe ser
reemplazada por algo nuevo. En este caso, Python sigue una política de obsolescencia basada
en un periodo de transición de un año en el que las características a renovar son consideradas
formalmente obsoletas. En el periodo intermedio, se debe emitir un aviso (deprecation warning)
de forma que los programadores tengan tiempo de actualizar su código. Los detalles completos
de la política de Python están documentados en el PEP 5. Los cambios sólo se hacen
en las versiones nuevas y normalmente pasan 18 meses entre versiones; ergo la norma es
una versión en el periodo.

La única excepción ha sido Python 3. La nueva rama ha sido específicamente creada para permitir cambios que
rompieran la compatibilidad, permitiendo así a los desarrolladores de Python corregir problemas que,
simplemente, no podían solucionarse dentro de la política actual. Por ejemplo, hacer las cadenas
Unicode por defecto y devolver iteradores en lugar de listas.



Líneas paralelas de desarrollo


Sabiendo que la transción a Python 3 llevaría tiempo (unos 5 años, según varias estimaciones),
habría cierto desarrollo paralelo entre 2 y 3.

Con Python 2.7 como versión final de Python 2, se acordó que el periodo de mantenimiento
se extendería por un periodo substancial. Tarde o temprano, los desarrolladores que quieran
migrar a versiones más nuevas deberán dar el salto a Python 3.

He aquí uno de los problemas...



Obsolescencias sorpresa


En un hilo en python-dev`<http://mail.python.org/pipermail/python-dev/2011-March/109010.html>`__,
se señaló que una función específica de la API C, PyCObject_AsVoidPtr, había sido eliminada
con lo que parecían insuficientes avisos. Y, sin embargo, la política adoptada se supone que debería
proteger contra eso. ¿Qué pasó?

El cambio fue parte de una migración mayor desde una API más antigua, PyCObject, a una nueva y
mejorada, PyCapsule. El problema es que PyCObject es la predeterminada, y desde luego,
la única API disponible en Python 2.6. En 2.7 pasó a estar considerada obsoleta, y en Python 3.2
no existe, y la nueva PyCapsule debe ser usada. Esto supone un periodo de tránsito entre el
lanzamiento de 2.7 (julio del 2010) al lanzamiento de 3.2 (febrero del 2011) de siete meses; mucho
menor al mínimo de doce meses exigido, y hace más difícil dar soporte a un rango razonable de
versiones de Python.

Para alguien migrando de 3.0 a 3.1 y después a 3.2, el tránsito es correcto. Python 3.1 fue
lanzado en marzo del 2010 con la marca de obsolescencia, por tanto, en la serie 3.x hay un periodo
de casi 12 meses. Sin embargo, esto no es lo habitual: migran de 2.7 directamente a la última
versión de 3.x; en nuestro caso, 3.2, apareciendo este problema. Nunca fue la intención del equipo
de desarrollo, pero PEP 5 no se escribió para desarrollos de dos versiones en paralelo.



Entonces, ¿qué hacemos?


Dado que el problema con la API PyCObject/PyCapsule está bien definido, no es imposible
de evitar, pero al menos una persona de python-dev ha tenido algunos problemas con ello.
En resumen, esto no debería haber ocurrido.

Para el caso específico de PyCObject/PyCapsule, el problema ya existía y no había mucho
que se pudiera hacer. Reincorporar PyCObject no era una opción, dado que sólo añadiría nuevas
incompatibilidades. Sin embargo, la visión general fue que era posible, aunque tedioso, escribir
código que se adaptara a cualquier API disponible. De hecho, en Python 3.1, la API PyCObject
fue escrita como un wrapper de la PyCapsule. Había una sugerencia de que, en caso de ser necesitada,
el código de la implementación en 3.1 podría ser extraído y ser usado como código para terceros.
Adicionalmente, se acordó que se escribiría un PEP "retroactivo" cubriendo el cambio, para describir
las razones tras el cambio y documentar los recursos que ayudarían a los programadores a migrar.

El equipo de Python ahora está al tanto de los problemas y trabajará para evitar que vuelvan a ocurrir.
Guido publicó una reseña
de la situación y sugirió que Python 3 debería ser conservativo dejando características obsoletas
por el momento. Como mínimo, las API consideradas obsoletas se conservarán más tiempo antes de ser
eliminadas, para dar a los programadores migrando desde 2.7 un camino más fácil.

Más indirectamente, el hilo mostró el problema de cómo comunicar de forma más efectiva los cambios
en Python a una audiencia mayor, de forma más oportuna; una de las razones de ser de este blog.



¿Qué significa todo esto?


En primer lugar, significa que los desarrolladores de Python no lo hacen todo bien. Nadie
quiere hacer la vida de los programadores más difícil, simplemente no fue algo que se viera a tiempo.

En segundo lugar, arreglar el problema puede hacer aún más daño, así que PyCObject no se
reincorporará. Aunque eso ayudaría a los programadores afectados por el cambio, en global haría los problemas
de compatibilidad más complejos. Mientras tanto, tendremos que sobreponernos al problema y seguir adelante.
La lección está aprendida, y no volveremos a cometer el mismo error de nuevo.

Una hecho positivo puesto de manifiesto es que el equipo de Python escucha lo que sus usarios tienen que decirles.
La compatibilidad es muy importante, y se pone todo el esfuerzo en hacer la transición a nuevas versiones
tan indolora como sea posible. En particular, los desarrolladores de bibliotecas deberían ser
capaces de soportar varias versiones de Python con un nivel adecuado de esfuerzo.

Finalmente, los desarrolladores no han abandonado 2.7. No se implementarán nuevas características
y no existirá 2.8, pero la visión de los usuarios de 2.7 todavía es importante. Estar seguros de
que los usuarios pueden migrar a 3.x cuando estén listos es de vital importancia para la comunidad de Python.


No hay comentarios:

Publicar un comentario en la entrada