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 Python y Documentació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: Bytes y cadenas como valores: |
| string.replace(datos[i],...) | data[i].replace(..) |
| urllib.urlencode() | Nuevos módulos
Ejemplos: |
| 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.
|
1 2 3 4 5 6 |
(mienv) jmunta-mac:myscripts jagadeshmunta$ 2a3 . -o nuevo -n -w . hq-mac:probador jagadeshmunta$ cd lib; mv lib/couchbase_ayudante ../couchbase_helper hq-mac:probador jagadeshmunta$ 2a3 -f todos -f búfer -f frases hechas -f set_literal -f ws_coma -n -o ~/p3testrunner_3 -w . |te ~/2to3_3.txt hq-mac:probador jagadeshmunta$ tiempo 2a3 -f todos -f búfer -f frases hechas -f set_literal -f ws_coma -n -w . |te ~/2to3_4.txt $ 2a3 -f todos -f búfer -f frases hechas -f set_literal -f ws_coma -n -o ~/p3testrunner_helper -w ../couchbase_helper |te ~/2to3_helper.txt cp -R ~/p3testrunner_helper/* . |
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
-
1234567Archivo "lib/mc_bin_client.py", línea 53, en __init__ si msg: supermsg += ": " + str(msg)TypeError: debe sea str, no bytesArchivo "lib/mc_bin_client.py", línea 141, en _recvMsgrespuesta += datosTypeError: debe sea str, no bytes
-
- Error#3. TypeError: se requiere un objeto tipo bytes, no 'str'.
-
1234567891011121314151617181920Archivo "lib/remote/remote_util.py", línea 3038, en log_command_output si "Warning" en línea y "hugepages" en línea:TypeError: a bytes-como objeto es obligatorio, no 'str'Archivo "lib/tasks/task.py", línea 1167, en run_high_throughput_mode subir Excepción(rv["err"])Excepción: a bytes-como objeto es obligatorio, no 'str'Archivo "lib/mc_bin_client.py", línea 936, en _set_vbucket auto.vbucketId = (((zlib.crc32(clave)) >> 16) & 0x7fff) & (auto.vbucket_count - 1)TypeError: a bytes-como objeto es obligatorio, no 'str'Archivo "lib/mc_bin_client.py", línea 148, en _recvMsgmagia = struct.desempaquetar(">B", respuesta[0:1])[0]TypeError: a bytes-como objeto es obligatorio, no 'str'Archivo "lib/remote/remote_util.py", línea 4560, en check_cmd si fuera y comando_salida en fuera[0]:TypeError: a bytes-como objeto es obligatorio, no 'str'
-
- Error#4. TypeError: No se pueden mezclar argumentos str y no str
-
1234567Archivo "lib/mc_bin_client.py", línea 126, en _sendMsg auto.s.enviar(msg + extraHeader + clave + val + datos_meta_extendidos)TypeError: puede't concat str a bytesArchivo "/usr/lib64/python3.6/urllib/parse.py", línea 120, en _coerce_argssubir TypeError("No se pueden mezclar argumentos str y no str")TypeError: No se puede mezcla str y no-str argumentos
-
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
|
1 2 |
si o[0] != b"": o = o[0].dividir(b" ") |
Rodea con try-except para comprobar la línea exacta que causa el error (digamos por encima de TypeError.)
|
1 2 3 4 5 6 7 8 9 10 11 |
importar rastreo pruebe: .. excepto Excepción como e: registro.información("{}".formato(e)) rastreo.imprimir_exc() exc_tipo, exc_obj, exc_tb = sys.exc_info() fname = ruta.os.dividir(exc_tb.tb_frame.f_code.co_filename)[1] imprimir(exc_tipo, fname, exc_tb.tb_lineno) |
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.
|
1 2 3 4 5 6 |
3079 para línea en salida: 3080 pruebe: 3081 línea=línea.descodificar() 3082 excepto AttributeError: 3083 pase |
3. Problema(s):
|
1 2 3 |
Archivo "lib/membase/api/rest_client.py", línea 4178, en recuento_multiscan_para_gsi_index_con_resto contenido = contenido.dividir("[]")[0] TypeError: a bytes-como objeto es obligatorio, no 'str' |
Solución(es):
|
1 |
contenido = contenido.dividir(b'[]')[0].descodificar() |
4. Problema(s):
AttributeError falta suite_setUp() o suite_tearDown() en algunos testsuites.
|
1 |
AttributeError: tipo objeto XDCRAdvFilterTests tiene no atributo 'suite_setUp' |
Solución(es):
Añade los métodos ficticios suite_setUp() y suite_tearDown().
|
1 2 3 4 5 6 7 8 |
11a12,18 > > def suite_setUp(auto): > imprimir("*** XDCRAdvFilterTests : suite_Setup() ***") > > def suite_tearDown(auto): > imprimir("*** XDCRAdvFilterTests : suite_tearDown() ***") > |
5. Problema(s):
|
1 2 3 |
Archivo "./testrunner.py", línea 416, en principal resultado.errores = [(nombre, e.mensaje)] AttributeError: AtributoError objeto tiene no atributo mensaje |
Solución(es):
|
1 |
resultado.errores = [(nombre, str(e))] |
6. Problema(s):
AttributeError: 'Transport' object has no attribute '_Thread__stop'
|
1 2 3 4 5 6 7 8 9 10 |
Archivo "./testrunner.py", línea 529, en principal t._Thread__stop() AttributeError: Transporte objeto tiene no atributo '_Thread__stop' Archivo "pytests/view/viewquerytests.py", línea 45, en stop auto._Thread__stop() AttributeError: StoppableThread objeto tiene no atributo '_Thread__stop' auto._stop() TypeError: Evento objeto es no Llamable |
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
|
1 2 3 4 5 6 7 8 |
def buildGoodSet(buenasCaras=cadena.imprimible, badChar='?'): 143 """Construye una tabla de traducción que convierta todos los caracteres que no estén en goodChars 144 a badChar"" 145 allChars = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123 456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x9 3\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\x bb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\ xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 146 badchars = str.maketrans(allChars, allChars, buenasCaras) 147 badchars1=str.traducir(allChars,badchars) 148 rv = str.maketrans(badchars1, badChar * len(badchars1)) 149 devolver rv |
8. Problema(s):
TabError: uso incoherente de tabuladores y espacios en la sangría
|
1 2 3 4 |
Archivo "pytests/seguridad/audittest.py", línea 396 concha = RemoteMachineShellConnection(auto.maestro) ^ TabError: inconsistente utilice de pestañas y espacios en 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.
|
1 |
sed -i 's/\t/ /g' pytests/seguridad/audittest.py |
9. Problema(s):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Archivo "lib/couchbase_helper/documentgenerator.py", línea 83, en __next__ valor = arg[semilla % len(arg)] TypeError: lista índices debe sea números enteros o rodajas, no float Archivo "lib/membase/helper/bucket_helper.py", línea 517, en cargar_algunos_datos llaves = ["key_%s_%d" % (testuuid, i) para i en gama(número_de_cubos)] TypeError: flotante objeto no puede sea interpretado como un entero Archivo "lib/membase/helper/bucket_helper.py", línea 372, en verifique_datos prueba.assertEqual(valor, clave, msg=los valores no coinciden) AssertionError: b'key_d918f450-5858-4430-a016-230e1f45bcf9_0' != 'key_d918f450-5858-4430-a016-230e1f45bcf9_0' : valores No match Archivo "pytests/setgettests.py", línea 90, en set_get_prueba auto.prueba.falla("valor incorrecto para la clave {0}".formato(clave)) AssertionError: valor desajuste para clave 9fcbd36f-e34d-477b-9fc5-0a5d067dff4b Archivo "pytests/seguridad/auditmain.py", línea 320, en returnFieldsDef si (isinstance((datos[campos_obligatorios][artículos.codificar(utf-8)]), dic)): KeyError: bnombre_cubo Archivo "lib/tasks/task.py", línea 2370, en Comprobar documento_revisión nuevo_rev_id = auto._parse_revision(meta[rev]) KeyError: rev |
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
|
1 2 3 |
Archivo "pytests/tuqquery/tuq_dml.py", línea 455, en test_insert_with_seleccione resultado_esperado = clasificado([{cubo.nombre: {nombre: doc[nombre]}} para doc en valores[:num_docs]]) TypeError: '<' no compatible entre instancias de 'dict' y 'dict' |
Solución(es):
|
1 |
resultado_esperado = clasificado(resultado_esperado,clave=(lambda x: x[cubo.nombre][nombre])) |
11. Problema(s):
|
1 2 3 |
Archivo "pytests/tuqquery/tuq_2i_index.py", línea 1057, en test_simple_array_índice auto.assertTrue(clasificado(resultado_real_dentro[Resultados]) == clasificado(resultado_esperado[Resultados])) TypeError: '<' no compatible entre instancias de 'dict' y 'dict' |
Solución(es):
|
1 2 3 |
- auto.assertTrue(clasificado(resultado_real_dentro[Resultados]) == clasificado(resultado_esperado[Resultados])) + auto.assertTrue(clasificado(resultado_real_dentro[Resultados], clave=(lambda x: x[nombre])) == \ + clasificado(resultado_esperado[Resultados], clave=(lambda x: x[nombre]))) |
12. Problema(s):
|
1 2 3 4 5 6 7 |
Archivo "pytests/tuqquery/tuq.py", línea 1221, en verificar_resultados auto.falla("Los resultados son incorrectos.Num real %s. Número esperado: %s.\n" % (len(resultado_real), len(resultado_esperado))) AssertionError: Resultados son incorrecto.Actual num 0. Previsto num: 72. Archivo "lib/tasks/task.py", línea 3638, en filtro_emitido_filas invertir=conjunto_descendente) TypeError: cmp es un inválido palabra clave argumento para este función |
Solución(es):
|
1 |
filas_esperadas = clasificado(auto.filas_emitidas, clave=(lambda x: (x[llave],x[id])),invertir=conjunto_descendente) |
13. Problema(s):
|
1 2 3 |
Archivo "lib/tasks/task.py", línea 3675, en <listcomp> filas_esperadas = [fila para fila en filas_esperadas si fila[llave] >= clave_inicio y fila[llave] <= fin_clave] TypeError: '>=' no compatible entre instancias de int y Ninguno |
Solución(es):
Aquí, debería devolver int ya que python 3 no compara automáticamente como en python 2.
14. Problema(s):
|
1 |
hasattr(artículos,'iteritems') no't devolver verdadero |
Solución(es):
|
1 2 3 4 5 6 7 8 |
@@ -754,7 +755,7 @@ clase MemcachedClient(objeto): # Si se trata de un dict, conviértalo en un generador de pares colección = auto.nombre_colección(colección) - si hasattr(artículos, iteritems): + si hasattr(artículos, artículos): artículos = iter(artículos.artículos()) si hasattr(artículos, artículos): |
15. Problema(s):
|
1 2 3 |
Archivo "lib/crc32.py", línea 78, en crc32_hash crc = (crc >> 8) ^ crc32tab[int((crc ^ ord(ch)) & 0xff)] TypeError: ord() esperado cadena de longitud 1, pero int encontrado |
Solución(es):
Convierte la clave a cadena para que ch sea cadena en lugar de int con clave binaria. Ver el archivo.
|
1 2 3 4 |
pruebe: clave = clave.descodificar() excepto AttributeError: pase |
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
|
1 2 3 4 5 |
Archivo "lib/remote/remote_util.py", línea 1714, en crear_directorio si e[0] == 2: TypeError: FileNotFoundError objeto es no suscribible - si e[0] == 2: + si e.errno == 2: |
17. Problema(s):
|
1 2 3 4 5 6 |
Traceback (más reciente llame a último): Archivo "lib/couchbase_helper/tuq_helper.py", línea 521, en ejecutar_consulta_y_verificar_resultado auto.verificar_resultados(sorted_actual_result, resultado_esperado_ordenado) Archivo "lib/couchbase_helper/tuq_helper.py", línea 114, en Verificar_resultados subir Excepción(msg) Excepción: En número de filas match pero el resultados desajuste, por favor consulte |
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'
|
1 2 3 |
Archivo "scripts/populateIni.py", línea 52, en principal datos[i] = cadena.sustituir(datos[i], dinámico, servidores[0]) AttributeError: módulo cadena tiene no atributo reemplazar |
Solución(es):
Utilice la variable str directa para reemplazar como se muestra a continuación para solucionar el problema.
|
1 |
datos[i].sustituir( dinámico, servidores[0]) |
19. Problema(s):
|
1 |
TypeError: '>' no compatible entre instancias de int y 'str' |
Solución(es):
Utilice la función str o int adecuadamente.
|
1 2 |
si donde_clausa: + donde_clausa = donde_clausa.sustituir('si t > "', 'if str(t) > "') # para corregir el error de tipo entre int, str comparación |
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):
|
1 2 3 |
Archivo "lib/couchbase_helper/tuq_helper.py", línea 782, en verificar_índices_redistribuido si cmp(items_count_before_rebalance, recuento_de_artículos_después_del_reequilibrio) != 0: ErrorNombre: nombre cmp es no definido |
Solución(es):
|
1 2 3 4 5 |
Utilice deepdiff módulo y DeepDiff clase a do objeto comparación. - si cmp(index_state_before_rebalance, index_state_after_rebalance) != 0: + si DeepDiff(index_state_before_rebalance, índice_sArchivo "lib/couchbase_helper/documentgenerator.py", línea 19, en tiene_siguiente devolver auto.itr < auto.fin TypeError: '<' no compatible entre instancias de int y 'str' |
Convierta str a int como se indica a continuación para el problema de error de tipo anterior.
|
1 |
devolver int(auto.itr) < int(auto.fin) |
—-
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.
- https://www.python.org/dev/peps/pep-0373/
- https://wiki.python.org/moin/Python2orPython3
- https://www.toptal.com/python/python-3-is-it-worth-the-switch
- https://weknowinc.com/blog/running-multiple-python-versions-mac-osx
- https://docs.python.org/3/howto/pyporting.html
- https://wsvincent.com/install-python3-mac/
- http://python3porting.com/pdfs/SupportingPython3-screen-1.0-latest.pdf
- https://riptutorial.com/Download/python-language.pdf
- https://docs.couchbase.com/python-sdk/2.5/start-using-sdk.html
- https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html
- https://pypi.org/project/deepdiff/
- https://buildmedia.readthedocs.org/media/pdf/portingguide/latest/portingguide.pdf
- 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.