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 |
(myenv) jmunta-mac:myscripts jagadeshmunta$ 2to3 . -o new -n -w . hq-mac:testrunner jagadeshmunta$ cd lib; mv lib/couchbase_helper ../couchbase_helper hq-mac:testrunner jagadeshmunta$ 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma -n -o ~/p3testrunner_3 -w . |tee ~/2to3_3.txt hq-mac:testrunner jagadeshmunta$ time 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma -n -w . |tee ~/2to3_4.txt $ 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma -n -o ~/p3testrunner_helper -w ../couchbase_helper |tee ~/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
-
1234567File "lib/mc_bin_client.py", line 53, in __init__ if msg: supermsg += ": " + str(msg)TypeError: must be str, not bytesFile "lib/mc_bin_client.py", line 141, in _recvMsgresponse += dataTypeError: must be str, not bytes
-
- Error#3. TypeError: se requiere un objeto tipo bytes, no 'str'.
-
1234567891011121314151617181920File "lib/remote/remote_util.py", line 3038, in log_command_output if "Warning" in line and "hugepages" in line:TypeError: a bytes-like object is required, not 'str'File "lib/tasks/task.py", line 1167, in run_high_throughput_mode raise Exception(rv["err"])Exception: a bytes-like object is required, not 'str'File "lib/mc_bin_client.py", line 936, in _set_vbucket self.vbucketId = (((zlib.crc32(key)) >> 16) & 0x7fff) & (self.vbucket_count - 1)TypeError: a bytes-like object is required, not 'str'File "lib/mc_bin_client.py", line 148, in _recvMsgmagic = struct.unpack(">B", response[0:1])[0]TypeError: a bytes-like object is required, not 'str'File "lib/remote/remote_util.py", line 4560, in check_cmd if out and command_output in out[0]:TypeError: a bytes-like object is required, not 'str'
-
- Error#4. TypeError: No se pueden mezclar argumentos str y no str
-
1234567File "lib/mc_bin_client.py", line 126, in _sendMsg self.s.send(msg + extraHeader + key + val + extended_meta_data)TypeError: can't concat str to bytesFile "/usr/lib64/python3.6/urllib/parse.py", line 120, in _coerce_argsraise TypeError("Cannot mix str and non-str arguments")TypeError: Cannot mix str and non-str arguments
-
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 |
if o[0] != b"": o = o[0].split(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 |
import traceback try: .. except Exception as e: log.info("{}".format(e)) traceback.print_exc() exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print(exc_type, 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 for line in output: 3080 try: 3081 line=line.decode() 3082 except AttributeError: 3083 pass |
3. Problema(s):
|
1 2 3 |
File "lib/membase/api/rest_client.py", line 4178, in multiscan_count_for_gsi_index_with_rest content = content.split("[]")[0] TypeError: a bytes-like object is required, not 'str' |
Solución(es):
|
1 |
content = content.split(b'[]')[0].decode() |
4. Problema(s):
AttributeError falta suite_setUp() o suite_tearDown() en algunos testsuites.
|
1 |
AttributeError: type object 'XDCRAdvFilterTests' has no attribute '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(self): > print("*** XDCRAdvFilterTests : suite_Setup() ***") > > def suite_tearDown(self): > print("*** XDCRAdvFilterTests : suite_tearDown() ***") > |
5. Problema(s):
|
1 2 3 |
File "./testrunner.py", line 416, in main result.errors = [(name, e.message)] AttributeError: 'AttributeError' object has no attribute 'message' |
Solución(es):
|
1 |
result.errors = [(name, str(e))] |
6. Problema(s):
AttributeError: 'Transport' object has no attribute '_Thread__stop'
|
1 2 3 4 5 6 7 8 9 10 |
File "./testrunner.py", line 529, in main t._Thread__stop() AttributeError: 'Transport' object has no attribute '_Thread__stop' File "pytests/view/viewquerytests.py", line 45, in stop self._Thread__stop() AttributeError: 'StoppableThread' object has no attribute '_Thread__stop' self._stop() TypeError: 'Event' object is not callable |
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(goodChars=string.printable, badChar='?'): 143 """Build a translation table that turns all characters not in goodChars 144 to 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, goodChars) 147 badchars1=str.translate(allChars,badchars) 148 rv = str.maketrans(badchars1, badChar * len(badchars1)) 149 return rv |
8. Problema(s):
TabError: uso incoherente de tabuladores y espacios en la sangría
|
1 2 3 4 |
File "pytests/security/audittest.py", line 396 shell = RemoteMachineShellConnection(self.master) ^ TabError: inconsistent use of tabs and spaces in indentation |
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/security/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 |
File "lib/couchbase_helper/documentgenerator.py", line 83, in __next__ value = arg[seed % len(arg)] TypeError: list indices must be integers or slices, not float File "lib/membase/helper/bucket_helper.py", line 517, in load_some_data keys = ["key_%s_%d" % (testuuid, i) for i in range(number_of_buckets)] TypeError: 'float' object cannot be interpreted as an integer File "lib/membase/helper/bucket_helper.py", line 372, in verify_data test.assertEqual(value, key, msg='values dont match') AssertionError: b'key_d918f450-5858-4430-a016-230e1f45bcf9_0' != 'key_d918f450-5858-4430-a016-230e1f45bcf9_0' : values dont match File "pytests/setgettests.py", line 90, in set_get_test self.test.fail("value mismatch for key {0}".format(key)) AssertionError: value mismatch for key 9fcbd36f-e34d-477b-9fc5-0a5d067dff4b File "pytests/security/auditmain.py", line 320, in returnFieldsDef if (isinstance((particulars['mandatory_fields'][items.encode('utf-8')]), dict)): KeyError: b'bucket_name' File "lib/tasks/task.py", line 2370, in _check_ddoc_revision new_rev_id = self._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 |
File "pytests/tuqquery/tuq_dml.py", line 455, in test_insert_with_select expected_result = sorted([{bucket.name: {'name': doc['name']}} for doc in values[:num_docs]]) TypeError: '<' not supported between instances of 'dict' and 'dict' |
Solución(es):
|
1 |
expected_result = sorted(expected_result,key=(lambda x: x[bucket.name]['name'])) |
11. Problema(s):
|
1 2 3 |
File "pytests/tuqquery/tuq_2i_index.py", line 1057, in test_simple_array_index self.assertTrue(sorted(actual_result_within['results']) == sorted(expected_result['results'])) TypeError: '<' not supported between instances of 'dict' and 'dict' |
Solución(es):
|
1 2 3 |
- self.assertTrue(sorted(actual_result_within['results']) == sorted(expected_result['results'])) + self.assertTrue(sorted(actual_result_within['results'], key=(lambda x: x['name'])) == \ + sorted(expected_result['results'], key=(lambda x: x['name']))) |
12. Problema(s):
|
1 2 3 4 5 6 7 |
File "pytests/tuqquery/tuq.py", line 1221, in _verify_results self.fail("Results are incorrect.Actual num %s. Expected num: %s.\n" % (len(actual_result), len(expected_result))) AssertionError: Results are incorrect.Actual num 0. Expected num: 72. File "lib/tasks/task.py", line 3638, in filter_emitted_rows reverse=descending_set) TypeError: 'cmp' is an invalid keyword argument for this function |
Solución(es):
|
1 |
expected_rows = sorted(self.emitted_rows, key=(lambda x: (x['key'],x['id'])),reverse=descending_set) |
13. Problema(s):
|
1 2 3 |
File "lib/tasks/task.py", line 3675, in <listcomp> expected_rows = [row for row in expected_rows if row['key'] >= start_key and row['key'] <= end_key] TypeError: '>=' not supported between instances of 'int' and 'NoneType' |
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(items,’iteritems’) doesn’t return true |
Solución(es):
|
1 2 3 4 5 6 7 8 |
@@ -754,7 +755,7 @@ class MemcachedClient(object): # If this is a dict, convert it to a pair generator collection = self.collection_name(collection) - if hasattr(items, 'iteritems'): + if hasattr(items, 'items'): items = iter(items.items()) if hasattr(items, 'items'): |
15. Problema(s):
|
1 2 3 |
File "lib/crc32.py", line 78, in crc32_hash crc = (crc >> 8) ^ crc32tab[int((crc ^ ord(ch)) & 0xff)] TypeError: ord() expected string of length 1, but int found |
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 |
try: key = key.decode() except AttributeError: pass |
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 |
File "lib/remote/remote_util.py", line 1714, in create_directory if e[0] == 2: TypeError: 'FileNotFoundError' object is not subscriptable - if e[0] == 2: + if e.errno == 2: |
17. Problema(s):
|
1 2 3 4 5 6 |
Traceback (most recent call last): File "lib/couchbase_helper/tuq_helper.py", line 521, in run_query_and_verify_result self._verify_results(sorted_actual_result, sorted_expected_result) File "lib/couchbase_helper/tuq_helper.py", line 114, in _verify_results raise Exception(msg) Exception: The number of rows match but the results mismatch, please check |
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 |
File "scripts/populateIni.py", line 52, in main data[i] = string.replace(data[i], 'dynamic', servers[0]) 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.
|
1 |
data[i].replace( 'dynamic', servers[0]) |
19. Problema(s):
|
1 |
TypeError: '>' not supported between instances of 'int' and 'str' |
Solución(es):
Utilice la función str o int adecuadamente.
|
1 2 |
if where_clause: + where_clause = where_clause.replace('if t > "', 'if str(t) > "') # to fix the type error between int, str comparison |
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 |
File "lib/couchbase_helper/tuq_helper.py", line 782, in verify_indexes_redistributed if cmp(items_count_before_rebalance, items_count_after_rebalance) != 0: NameError: name 'cmp' is not defined |
Solución(es):
|
1 2 3 4 5 |
Use deepdiff module and DeepDiff class to do object comparison. - if cmp(index_state_before_rebalance, index_state_after_rebalance) != 0: + if DeepDiff(index_state_before_rebalance, index_sFile "lib/couchbase_helper/documentgenerator.py", line 19, in has_next return self.itr < self.end TypeError: '<' not supported between instances of 'int' and 'str' |
Convierta str a int como se indica a continuación para el problema de error de tipo anterior.
|
1 |
return int(self.itr) < int(self.end) |
—-
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/
- https://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
- https://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.