Buenas prácticas y tutoriales

Cómo actualizar Python 2 a Python 3 y sus diferencias

Introducción

La última actualización importante de Python -a la versión 3- llegó en diciembre de 2008, hace casi 12 años. Y, sin embargo, es muy probable que todavía estés trabajando en el producto o código de prueba de Python 2. Si es así, puede que estés viendo el siguiente mensaje de depreciación como recordatorio para actualizar la versión de Python con la que estás trabajando.

"DEPRECCIÓN: Python 2.7 llegará al final de su vida útil el 1 de enero de 2020. Por favor, actualice su Python ya que Python 2.7 no se mantendrá después de esa fecha. Una versión futura de pip dejará de soportar Python 2.7."

Por favor, tómese esto en serio y planifique en consecuencia: Las actualizaciones de Python a 3.x no son compatibles con versiones anteriores. Lo que escribas con versiones de Python 2.x puede que no funcione correctamente al usar 3.x.

Asegúrate también de leer la letra pequeña. Según el sitio web del lenguaje de programación, la fecha de lanzamiento de la actualización final de Python aún está por determinar: "Al ser la última de la serie 2.x, la 2.7 recibirá soporte de corrección de errores hasta 2020. El soporte cesa oficialmente el 1 de enero de 2020, pero la versión final se producirá después de esa fecha." [1]

Así pues, Python 2 entrará en modo no soportado a finales de este año. Si aún no lo has hecho, ahora es un buen momento para migrar el código actual de Python 2 a la sintaxis de Python 3 y seguir con Python 3 en adelante.

¿Por qué los equipos no se lanzan a la migración de Python 2 a 3? Uno de los mayores obstáculos es que la mayoría del código que funciona simplemente se rompe (leer más en por qué-python-3-se-hizo-incompatible-con-python-2), ya sea por la sintaxis directa del lenguaje o por problemas con APIs de terceros. Seamos justos: pocos de nosotros nos molestaríamos en migrar si las nuevas actualizaciones de Python fueran compatibles con versiones anteriores. En lugar de eso, la versión 2 se quedará sin soporte, forzando a muchos -incluidos nosotros aquí en Couchbase- a priorizar la migración. Incluso si el equipo cruza la fecha límite de soporte de corrección de errores, no pasa nada (porque tu código sigue funcionando). Como equipo, hemos decidido que es mejor migrar tan cerca de esta fecha como sea posible para que estemos en la misma página con otros miembros de la comunidad Python y aprender junto a ellos.  

Este documento es una colección de consejos y trucos que aprendimos mientras actualizábamos a Python 3 junto con problemas comunes que encontramos durante el proceso de migración de la infra prueba de Couchbase. Como verás, actualizamos python manualmente por línea de comandos después de empezar con un proceso automatizado. Tu enfoque puede ser diferente. En cualquier caso, empieza tan pronto como puedas. Actualizar python de la versión 2 a la versión 3 es importante.

Couchbase es una base de datos NoSQL MultiCloud to Edge de código abierto para empresas. El framework de pruebas funcionales de Couchbase, TestRunner ha sido desarrollado en Python 2. El repositorio git de TestRunner se puede encontrar en https://github.com/couchbase/testrunner . Nuestro objetivo ahora es cambiar completamente al tiempo de ejecución de Python 3 en lugar de co-ejecutar con Python 3 y Python 2.

Como parte del proceso de actualización de Python, hemos identificado los principales cambios necesarios para portar con éxito a la versión 3. Algunos de los problemas sobre los que leerás los identificamos durante el proceso de migración. Nuestro objetivo al compartir nuestros aprendizajes es ayudarte con tu propia migración. Puedes elegir la última versión de Python 3.x (depende de la versión pre-lanzamiento, estable, con correcciones de seguridad en una plataforma específica, 3.7 o 3.6), a la que nos referiremos como Python 3 a lo largo de este blog. Más información sobre la versión en Descarga de versiones de PythonDocumentación sobre Python 3.

Hoja de trucos

 

Cambios importantes: Python 2 frente a Python 3

Para hacerse una idea de las principales diferencias entre Python 2 y Python 3, he aquí la lista resumida de los cambios de código necesarios.

Python 2 Python 3
Texto utf-8 : str
El texto es unicode : str
u"
Binario es lo mismo que Texto: bytes/str
Por ejemplo:
file.read(6) == 'GIF89a'
Los datos binarios se representan con el prefijo b: bytes
 b"
Usa decode() para obtener la cadena, encode() para obtener bytes.Ejemplos: 
file.read(6) == b'GIF89a'
b'hola'.decode() → 'hola'
'hola'.encode() → b'hola'
str(b'hola') → "b'hola'
Imprimir declaración
Ejemplo: imprimir ' '
Función de impresión
Ejemplo:print(' ')
División entera
Ejemplo: 5/2=2
División de pisos. Utilice 2 barras oblicuas
Ejemplo: 5//2 = 2 y 5/2=2,5
División flotante
Ejemplo: 5/2,0 = 2,5 ó 5,0/2 = 2,5
División flotante. Utilizar barra simple
Ejemplo: 5/2 = 2.5
El tipo long es diferente de int
largo 
No existe el tipo long. Es igual que int
xrange() rango()
Las funciones de iteración tenían el prefijo iter. iterxxx()
Ejemplo: iteritems()
Se ha eliminado el prefijo iter. xxxx()
Ejemplo: items()
Las listas se cargan directamente (todos los elementos se cargan en memoria cuando se utiliza la lista)
Ejemplo: para i en [] 
Las listas se cargan lentamente (cuando se accede a un elemento, sólo se carga en memoria).
Ejemplo: for i in list([]) 
Los diccionarios pueden compararse por defecto o contra 2 dict.
Ejemplo: sorted(dict) 
Los diccionarios no se pueden comparar directamente. sorted() debe tener clave.

Por ejemplo: sorted(resultado_esperado,key=(lambda x: x[cubo.nombre]['nombre']))Para la comparación general de dictados/listas, puede utilizar lo siguiente: 
 from deepdiff import DeepDiff
 diffs = DeepDiff(resultado_actual['resultados'], resultado_esperado[Resultados], ignorar_orden=Verdadero)si diferencias:
   auto.assertTrue(Falso, diffs)

Bytes y cadenas como valores:
diffs = DeepDiff(configure(índices_actuales), configure(nombres_índices), ignorar_orden=Verdadero, ignore_string_type_changes=Verdadero)

string.replace(datos[i],...) data[i].replace(..)
urllib.urlencode() Nuevos módulos

  • cliente.http
  • urllib.request, urllib.error, urllib.parse
  • sgmllib3k

Ejemplos: 
urllib.parse.urlencode()

cadena.minúsculas Atributos:
string.ascii_lowercase
string.ascii_uppercase

Véase el testrunner py3 commits  para cambios

Configuración de Python 3

Para configurar Python 3 desde cero, ejecute los siguientes comandos en un nuevo host con las principales plataformas soportadas.
Más tarde, durante el tiempo de ejecución, o bien utilizar el comando python 3 o python en python 3 virtual env. Utilice pip3 o pip3.x (pip3.6 por ejemplo) para instalar paquetes basados en la versión Python 3 instalada.

Mac OS
(Ejemplo: tu portátil)
Instalación directa (pip3 se instala automáticamente):(https://wsvincent.com/install-python3-mac/)

Configuración del entorno virtual:

Instale las bibliotecas necesarias:

Por ahora, la siguiente modificación es necesaria para el cliente http común de Python 3, de lo contrario, se produciría un error.

 
CentOS  
(Nodo de ejemplo: Jenkins Esclavo)
Configuración directa y entorno virtual:

Instale las bibliotecas necesarias:

 

Realiza la instalación de Couchbase CSDK y Python SDK en el nuevo esclavo:

Por ahora, la siguiente modificación es necesaria para el cliente http común de Python 3, de lo contrario, se produciría un error.

 

Esclavo Ubuntu utilizando para Python 3 verificación en tiempo de ejecución
Instalación directa:

 

Instale las bibliotecas necesarias:

Instalación de CSDK y Python SDK: (Ref: https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html )

Por ahora, la siguiente modificación es necesaria para el cliente http común de Python 3, de lo contrario, se produciría un error.

 

Windows
Descárgalo e instálalo: https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe

Instale las bibliotecas necesarias:

 

Proceso de migración

A grandes rasgos, la portabilidad es un proceso de tres pasos. 1) Conversión automática 2) Cambios manuales 3) Validación y corrección en tiempo de ejecución

Al principio, clone el repositorio original y realice los cambios básicos de conversión automática. Checkin los cambios como un nuevo repositorio hasta que la conversión completa se hace. De esta manera, los ciclos de regresión actuales pueden ir sin interrupción.

1. Conversión automática

Existe una herramienta automatizada llamada 2a3 herramientaproporcionado por el equipo de Python 3, que ayuda a resolver algunos problemas comunes como la impresión, las excepciones, el empaquetado de listas, las importaciones relativas, etc.  

Puede empezar con un único directorio en el espacio de trabajo clonado localmente para hacer una doble comprobación. Más tarde, la conversión se puede hacer por completo en todo el código de modo que la portabilidad básica se lleva a cabo.

A continuación se muestran algunos ejemplos de comandos de conversión de 2 a 3 en MacOS. En el último comando, observe que se han aplicado todos los modismos. De esta manera, la primera vez que la conversión puede hacerse cargo de los cambios de clave.

 

2. Cambios manuales

La conversión automática no realiza la portabilidad completa. Los siguientes problemas comunes pueden ser experimentados durante el proceso de portabilidad que los cambios de sintaxis comunes realizados por la herramienta de conversión automática 2to3. 

Ejecutar la clase de prueba y ver si hay algún error y corregirlo adecuadamente, decidiendo si hay que cambiar de bytes a str o de str a bytes o algún problema de tipo/comparación en el que haya que corregir el nombre de la clave en la función ordenada. Se trata de un proceso iterativo hasta que se haya validado todo el tiempo de ejecución del código.

Una vez que un patrón común seguro es claro, entonces usted puede hacer grep y sed para reemplazar a través de muchos archivos de clase. Si usted no está seguro acerca de otro código hasta el tiempo de ejecución, a continuación, aplazar hasta que la clase de prueba se ejecuta. 

Puede haber problemas con librerías/módulos de terceros que pueden haber cambiado, hay que buscarlos en la web y utilizarlos adecuadamente.

Asegúrese de que se cubre toda la ruta del código ejecutándolo en todas las plataformas y parámetros compatibles.

3. Validación y corrección en tiempo de ejecución

Una vez realizada la conversión, a continuación, realizar un montón de tiempo de ejecución de código como Python es un lenguaje dinámico. De lo contrario, los cambios pueden romper las cosas si usted hace sólo visual estática de inspección de código / cambios. Usted puede comenzar con pruebas básicas de sanidad, pruebas de aceptación y luego seleccionar pruebas completas de un solo módulo de pruebas.

Una vez que se sienta cómodo, entonces vaya con todos los demás módulos uno por uno. Sigue comprobando los cambios en el nuevo repositorio. Además, necesitas asegurarte de que no hay regresiones con los cambios portados desde este nuevo repositorio ejecutando pruebas de sanidad en las nuevas compilaciones. Además, la validación debe incluir todas las plataformas soportadas con Python 3.

 

Código portado de Python 3 y estado

A continuación se muestra dónde encontrar el nuevo repositorio para el código portado de Python 3 hasta que se fusione con el repositorio principal. El plan es hacer un ciclo de portabilidad o tomar los cambios del repositorio principal y hacer una fusión manual a este.

https://github.com/couchbaselabs/testrunner-py3/

(Rama: master)

Muchos cambios comunes ya se han realizado pero no se han completado, ya que puede haber otros problemas en tiempo de ejecución. Las correcciones en común también pueden retroceder a las correcciones anteriores debido a las suposiciones sobre las conversiones del tipo de valor de entrada. Aún queda código portado por validar con Python 3 y el esfuerzo sigue en marcha.

Ahora, permítanme mostrarles los problemas comunes que ocurrió durante la validación en tiempo de ejecución. Usted puede utilizar esto como una referencia cuando usted golpea un problema para ver si usted está teniendo el problema similar. Usted puede aplicar la misma solución y ver si funciona para usted. Y si tienes alguna nuevas ideas, puedes ponerlas en los comentarios.

Problemas comunes en tiempo de ejecución

 

1. Problema(s):

  • Es posible que se produzcan algunos de los siguientes TypeErrors durante la ejecución, como str en lugar de bytes y bytes en lugar de str
  • Error#1. TypeError: can't concat str to bytes
  • Error#2. TypeError: debe ser str, no bytes
  • Error#3. TypeError: se requiere un objeto tipo bytes, no 'str'.
  • Error#4. TypeError: No se pueden mezclar argumentos str y no str

Solución(es):

Vea los tipos de las variables en la sentencia y use xxx.encode() para obtener los bytes o xxx.decode() para obtener la cadena o use b prefix o use str(). A veces, la entrada puede no ser desconocida y en este caso, use try x.encode() except AttributeError: pass


2. Problema(s):

TypeError: root - ERROR - --->instalación fallida: se requiere un objeto tipo bytes, no 'str'

Solución(es): 

En este caso, añada b como prefijo a la cadena objeto de comparación o cambie el tipo byte por el tipo cadena. Ejemplo: lib/remote/remote_util.py

Rodea con try-except para comprobar la línea exacta que causa el error (digamos por encima de TypeError.) 

Ejemplo de salida después de traceback.print_exec() para ver el stack trace completo en similar a java.

Arreglar con cambios a lib/remote/remote_util.py como abajo.

3. Problema(s):

 

Solución(es):

 

4. Problema(s):

AttributeError falta suite_setUp() o suite_tearDown() en algunos testsuites.

Solución(es):

Añade los métodos ficticios suite_setUp() y suite_tearDown(). 

 

5. Problema(s):

 

Solución(es):

 

6. Problema(s):

AttributeError: 'Transport' object has no attribute '_Thread__stop'

Solución(es):

No hay parada directa de un hilo no daemónico. Pero sintácticamente se puede usar t._stop(). La recomendación es usar el graceful shutdown usando una bandera global y comprobar en el run() del hilo para romper.

(https://stackoverflow.com/questions/27102881/python-threading-self-stop-event-object-is-not-callable)

7. Problema(s):

No se encontró la prueba expirytests.ExpiryTests.test_expired_keys: el módulo 'string' no tiene el atributo 'translate'.

Solución(es):

Reescribir con métodos estáticos str. No hay forma antigua de obtener todos los chars, así que usamos el código anterior y usamos total set.

vi lib/membase/api/tap.py 

 

8. Problema(s):

TabError: uso incoherente de tabuladores y espacios en la sangría

 

Solución(es):

Buscar caracteres de tabulación y sustituirlos por caracteres de espacio. 

Para el problema anterior, elimine los caracteres de tabulación.

 

9. Problema(s):

Solución(es):

Problema de sensibilidad a mayúsculas y minúsculas. Corregido cambiando de clave x_couchbase_meta a X_Couchbase_Meta.

 

10. Problema(s):

  • Error#1. TypeError: '<' no soportado entre instancias de 'dict' y 'dict'.
  • Error#2. TypeError: 'cmp' es un argumento de palabra clave no válido para esta función

Solución(es):

   

11. Problema(s):

Solución(es):

 

12. Problema(s):

Solución(es):

 

13. Problema(s):

Solución(es):

Aquí, debería devolver int ya que python 3 no compara automáticamente como en python 2.

 

14. Problema(s):

Solución(es):

 

15. Problema(s):

Solución(es):

Convierte la clave a cadena para que ch sea cadena en lugar de int con clave binaria. Ver el archivo.

 

16. Problema(s):

TypeError: El objeto 'FileNotFoundError' no es sub-scriptible

Solución(es):

Cambiado en Python 3 como FileNotFoundError no es sub-scriptable y en su lugar, utilizar el atributo errno, e.errno

 

17. Problema(s):

Solución(es):

La comparación diccionario/lista anidada no funcionaba debido a que la función sorted anterior para ordenar completamente ahora no está disponible. Utilice el módulo deepdiff y la clase DeepDiff para realizar la comparación

 

18. Problema(s):

AttributeError: module 'string' has no attribute 'replace'

Solución(es):

Utilice la variable str directa para reemplazar como se muestra a continuación para solucionar el problema.

 

19. Problema(s):

Solución(es):

Utilice la función str o int adecuadamente.

 

20. Problema(s):

NameError: el nombre 'cmp' no está definido

Solución(es):

Utiliza el módulo deepdiff y la clase DeepDiff para comparar objetos.

 

21. Problema(s):

Solución(es):

Convierta str a int como se indica a continuación para el problema de error de tipo anterior.

—-

Esto es todo por ahora en la lista de problemas a tener en cuenta cuando actualices Python versión 2 a Python versión 3. Publicaremos más aprendizajes en futuras entradas del blog. Mientras tanto, ¡buena suerte con la migración!

 

Otras lecturas

Las siguientes referencias nos ayudaron. También puede leer más en los siguientes enlaces de referencia para obtener más detalles y mejorar su código de portar a Python 3.

  1. https://www.python.org/dev/peps/pep-0373/
  2. https://wiki.python.org/moin/Python2orPython3
  3. https://www.toptal.com/python/python-3-is-it-worth-the-switch
  4. https://weknowinc.com/blog/running-multiple-python-versions-mac-osx
  5. https://docs.python.org/3/howto/pyporting.html
  6. https://wsvincent.com/install-python3-mac/
  7. http://python3porting.com/pdfs/SupportingPython3-screen-1.0-latest.pdf
  8. https://riptutorial.com/Download/python-language.pdf
  9. https://docs.couchbase.com/python-sdk/2.5/start-using-sdk.html
  10. https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html
  11. https://pypi.org/project/deepdiff/
  12. https://buildmedia.readthedocs.org/media/pdf/portingguide/latest/portingguide.pdf
  13. http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf

Espero que hayan pasado un buen rato leyendo.

Descargo de responsabilidad: Por favor, vea esto como una referencia rápida para su actualización a Python 3, más que como una guía completa para resolver problemas de portabilidad. Nuestra intención aquí es ayudarte en algún nivel y darte un empujón en el proceso de portabilidad. Por favor, siéntete libre de compartir si has aprendido algo nuevo que pueda ayudarnos. Agradecemos sus comentarios positivos.

 

Gracias a Raju Suravarjjala y Keshav Murthy por sus aportaciones y comentarios clave.

 

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Jagadesh Munta, Ingeniero Principal de Software, Couchbase

Jagadesh Munta es Ingeniero Principal de Software en Couchbase Inc. EE.UU. Anteriormente, trabajó en Sun Microsystems y Oracle durante 19 años. Jagadesh tiene un máster en Ingeniería de Software por la Universidad Estatal de San José (EE.UU.) y un B.Tech. Computer Science and Engineering en JNTU, India. Es autor de "Software Quality and Java Automation Engineer Survival Guide" para ayudar a los desarrolladores de software y a los ingenieros de automatización de la calidad.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.