{"id":7726,"date":"2019-10-13T14:34:34","date_gmt":"2019-10-13T21:34:34","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=7726"},"modified":"2025-06-13T21:25:16","modified_gmt":"2025-06-14T04:25:16","slug":"tips-and-tricks-for-upgrading-from-python-2-to-python-3","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","title":{"rendered":"C\u00f3mo actualizar Python 2 a Python 3 y sus diferencias"},"content":{"rendered":"<h2><span style=\"font-weight: 400\">Introducci\u00f3n<\/span><\/h2>\n<p><span style=\"font-weight: 400\">La \u00faltima actualizaci\u00f3n importante de Python -a la versi\u00f3n 3- lleg\u00f3 en diciembre de 2008, hace casi 12 a\u00f1os. Y, sin embargo, es muy probable que todav\u00eda est\u00e9s trabajando en el producto o c\u00f3digo de prueba de Python 2. Si es as\u00ed, puede que est\u00e9s viendo el siguiente mensaje de depreciaci\u00f3n como recordatorio para actualizar la versi\u00f3n de Python con la que est\u00e1s trabajando.<\/span><\/p>\n<p><span style=\"font-weight: 400\">\"DEPRECCI\u00d3N: Python 2.7 llegar\u00e1 al final de su vida \u00fatil el 1 de enero de 2020. Por favor, actualice su Python ya que Python 2.7 no se mantendr\u00e1 despu\u00e9s de esa fecha. Una versi\u00f3n futura de pip dejar\u00e1 de soportar Python 2.7.\"<\/span><\/p>\n<p><span style=\"font-weight: 400\">Por favor, t\u00f3mese 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<\/span><span style=\"font-weight: 400\">.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400\">Aseg\u00farate tambi\u00e9n de leer la letra peque\u00f1a. Seg\u00fan el sitio web del lenguaje de programaci\u00f3n, la fecha de lanzamiento de la actualizaci\u00f3n final de Python a\u00fan est\u00e1 por determinar: \"Al ser la \u00faltima de la serie 2.x, la 2.7 recibir\u00e1 soporte de correcci\u00f3n de errores hasta 2020. El soporte cesa oficialmente el 1 de enero de 2020, pero la versi\u00f3n final se producir\u00e1 despu\u00e9s de esa fecha.\" [<a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0373\/#update\">1<\/a>]<\/span><\/p>\n<p><span style=\"font-weight: 400\">As\u00ed pues, Python 2 entrar\u00e1 en modo no soportado a finales de este a\u00f1o. Si a\u00fan no lo has hecho, ahora es un buen momento para migrar el c\u00f3digo actual de Python 2 a la sintaxis de Python 3 y seguir con Python 3 en adelante. <\/span><\/p>\n<p><span style=\"font-weight: 400\">\u00bfPor qu\u00e9 los equipos no se lanzan a la migraci\u00f3n de Python 2 a 3? Uno de los mayores obst\u00e1culos es que la mayor\u00eda del c\u00f3digo que funciona simplemente se rompe (leer m\u00e1s en <\/span><a href=\"https:\/\/python-notes.curiousefficiency.org\/en\/latest\/python3\/questions_and_answers.html#why-was-python-3-made-incompatible-with-python-2\"><span style=\"font-weight: 400\">por qu\u00e9-python-3-se-hizo-incompatible-con-python-2<\/span><\/a><span style=\"font-weight: 400\">), ya sea por la sintaxis directa del lenguaje o por problemas con APIs de terceros. Seamos justos: pocos de nosotros nos molestar\u00edamos en migrar si las nuevas actualizaciones de Python fueran compatibles con versiones anteriores. En lugar de eso, la versi\u00f3n 2 se quedar\u00e1 sin soporte, forzando a muchos -incluidos nosotros aqu\u00ed en Couchbase- a priorizar la migraci\u00f3n. Incluso si el equipo cruza la fecha l\u00edmite de soporte de correcci\u00f3n de errores, no pasa nada (porque tu c\u00f3digo 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\u00e1gina con otros miembros de la comunidad Python y aprender junto a ellos.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Este documento es una colecci\u00f3n de consejos y trucos que aprendimos mientras actualiz\u00e1bamos a Python 3 junto con problemas comunes que encontramos durante el proceso de migraci\u00f3n de la infra prueba de Couchbase. Como ver\u00e1s, actualizamos python manualmente por l\u00ednea de comandos despu\u00e9s de empezar con un proceso automatizado. Tu enfoque puede ser diferente. En cualquier caso, empieza tan pronto como puedas. Actualizar python de la versi\u00f3n 2 a la versi\u00f3n 3 es importante.<\/span><\/p>\n<p><a href=\"https:\/\/www.couchbase.com\/blog\/es\/downloads\/\"><span style=\"font-weight: 400\">Couchbase<\/span><\/a><span style=\"font-weight: 400\"> es una base de datos NoSQL MultiCloud to Edge de c\u00f3digo 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<\/span><a href=\"https:\/\/github.com\/couchbase\/testrunner\"> <span style=\"font-weight: 400\">https:\/\/github.com\/couchbase\/testrunner<\/span><\/a><span style=\"font-weight: 400\"> .  Nuestro objetivo ahora es cambiar completamente al tiempo de ejecuci\u00f3n de Python 3 en lugar de co-ejecutar con Python 3 y Python 2.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Como parte del proceso de actualizaci\u00f3n de Python, hemos identificado los principales cambios necesarios para portar con \u00e9xito a la versi\u00f3n 3. Algunos de los problemas sobre los que leer\u00e1s los identificamos durante el proceso de migraci\u00f3n. Nuestro objetivo al compartir nuestros aprendizajes es ayudarte con tu propia migraci\u00f3n. Puedes elegir la \u00faltima versi\u00f3n de Python 3.x (depende de la versi\u00f3n pre-lanzamiento, estable, con correcciones de seguridad en una plataforma espec\u00edfica, 3.7 o 3.6), a la que nos referiremos como Python 3 a lo largo de este blog. M\u00e1s informaci\u00f3n sobre la versi\u00f3n en <\/span><a href=\"https:\/\/www.python.org\/downloads\/\"><span style=\"font-weight: 400\">Descarga de versiones de Python<\/span><\/a><span style=\"font-weight: 400\"> y\u00a0 <\/span><span style=\"font-weight: 400\"><a href=\"https:\/\/docs.python.org\/3\">Documentaci\u00f3n sobre Python 3<\/a>.<\/span><\/p>\n<p>Hoja de trucos<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Cambios importantes: Python 2 frente a Python 3<\/span><\/h2>\n<p>Para hacerse una idea de las principales diferencias entre Python 2 y Python 3, he aqu\u00ed la lista resumida de los cambios de c\u00f3digo necesarios.<\/p>\n<div class=\"responsive-table\">\n<table border=\"1\">\n<tbody>\n<tr>\n<td><b>Python 2<\/b><\/td>\n<td><b>Python 3<\/b><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Texto utf-8 : str<\/span><br \/>\n<span style=\"font-weight: 400\">&#8216;<\/span><span style=\"font-weight: 400\">&#8216;<\/span><\/td>\n<td><span style=\"font-weight: 400\">El texto es unicode : str<\/span><br \/>\n<span style=\"font-weight: 400\">u\"<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Binario es lo mismo que Texto: bytes\/str<\/span><br \/>\n<span style=\"font-weight: 400\">Por ejemplo:<\/span><br \/>\n<span style=\"font-weight: 400\">file.read(6) == 'GIF89a'<\/span><\/td>\n<td><span style=\"font-weight: 400\">Los datos binarios se representan con el prefijo b: bytes<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0b\"<\/span><br \/>\n<span style=\"font-weight: 400\">Usa decode() para obtener la cadena, encode() para obtener bytes.<\/span><span style=\"font-weight: 400\">Ejemplos:\u00a0<\/span><br \/>\n<span style=\"font-weight: 400\">file.read(6) == b'GIF89a'<\/span><br \/>\n<span style=\"font-weight: 400\">b'hola'.decode() \u2192 'hola'<\/span><br \/>\n<span style=\"font-weight: 400\">'hola'.encode() \u2192 b'hola'<\/span><br \/>\n<span style=\"font-weight: 400\"><span style=\"font-weight: 400\">str(b'hola') \u2192 \"b'hola'<\/span><\/span>&#8220;<\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Imprimir declaraci\u00f3n<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: imprimir ' '<\/span><\/td>\n<td><span style=\"font-weight: 400\">Funci\u00f3n de impresi\u00f3n<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo:print(' ')<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Divisi\u00f3n entera<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: 5\/2=2<\/span><\/td>\n<td><span style=\"font-weight: 400\">Divisi\u00f3n de pisos. Utilice 2 barras oblicuas<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: 5\/\/2 = 2 y 5\/2=2,5<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Divisi\u00f3n flotante<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: 5\/2,0 = 2,5 \u00f3 5,0\/2 = 2,5<\/span><\/td>\n<td><span style=\"font-weight: 400\">Divisi\u00f3n flotante. Utilizar barra simple<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: 5\/2 = 2.5<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">El tipo long es diferente de int<\/span><br \/>\n<span style=\"font-weight: 400\">largo\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">No existe el tipo long. Es igual que int<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">xrange()<\/span><\/td>\n<td><span style=\"font-weight: 400\">rango()<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Las funciones de iteraci\u00f3n ten\u00edan el prefijo iter. iterxxx()<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: iteritems()<\/span><\/td>\n<td><span style=\"font-weight: 400\">Se ha eliminado el prefijo iter. xxxx()<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: items()<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Las listas se cargan directamente (todos los elementos se cargan en memoria cuando se utiliza la lista)<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: para i en []\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">Las listas se cargan lentamente (cuando se accede a un elemento, s\u00f3lo se carga en memoria).<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: for i in list([])\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Los diccionarios pueden compararse por defecto o contra 2 dict.<\/span><br \/>\n<span style=\"font-weight: 400\">Ejemplo: sorted(dict)\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">Los diccionarios no se pueden comparar directamente. sorted() debe tener clave.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Por ejemplo: <\/span><span style=\"font-weight: 400\">sorted(resultado_esperado,key=(lambda x: x[cubo.nombre]['nombre']))<\/span><span style=\"font-weight: 400\">Para la comparaci\u00f3n general de dictados\/listas, puede utilizar lo siguiente:\u00a0<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0from deepdiff import DeepDiff<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0<\/span><span style=\"font-weight: 400\">diffs = DeepDiff(resultado_actual['resultados'], resultado_esperado[<\/span><b>Resultados<\/b><span style=\"font-weight: 400\">], <\/span><span style=\"font-weight: 400\">ignorar_orden<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadero<\/b><span style=\"font-weight: 400\">)<\/span><b>si <\/b><span style=\"font-weight: 400\">diferencias:<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400\">auto<\/span><span style=\"font-weight: 400\">.assertTrue(<\/span><b>Falso<\/b><span style=\"font-weight: 400\">, diffs)<\/span><\/p>\n<p><span style=\"font-weight: 400\">Bytes y cadenas como valores:<\/span><br \/>\n<span style=\"font-weight: 400\">diffs = DeepDiff(<\/span><span style=\"font-weight: 400\">configure<\/span><span style=\"font-weight: 400\">(\u00edndices_actuales), <\/span><span style=\"font-weight: 400\">configure<\/span><span style=\"font-weight: 400\">(nombres_\u00edndices), <\/span><span style=\"font-weight: 400\">ignorar_orden<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadero<\/b><span style=\"font-weight: 400\">, <\/span><span style=\"font-weight: 400\">ignore_string_type_changes<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadero<\/b><span style=\"font-weight: 400\">)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">string.replace(datos[i],...)<\/span><\/td>\n<td><span style=\"font-weight: 400\">data[i].replace(..)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">urllib.urlencode()<\/span><\/td>\n<td><span style=\"font-weight: 400\">Nuevos m\u00f3dulos<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">cliente.http<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">urllib.request, urllib.error, urllib.parse<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">sgmllib3k<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Ejemplos:\u00a0<\/span><br \/>\n<span style=\"font-weight: 400\">urllib.parse.urlencode()<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">cadena.min\u00fasculas<\/span><\/td>\n<td><span style=\"font-weight: 400\">Atributos:<\/span><br \/>\n<span style=\"font-weight: 400\">string.ascii_lowercase<\/span><br \/>\n<span style=\"font-weight: 400\">string.ascii_uppercase<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><span style=\"font-weight: 400\">V\u00e9ase el <\/span><a href=\"https:\/\/github.com\/couchbaselabs\/testrunner-py3\/commits\/master\"><span style=\"font-weight: 400\">testrunner py3 commits<\/span><\/a><span style=\"font-weight: 400\">\u00a0 para cambios<\/span><\/p>\n<h2><\/h2>\n<h2><span style=\"font-weight: 400\">Configuraci\u00f3n de Python 3<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Para configurar Python 3 desde cero, ejecute los siguientes comandos en un nuevo host con las principales plataformas soportadas.<\/span><br \/>\n<span style=\"font-weight: 400\">M\u00e1s tarde, durante el tiempo de ejecuci\u00f3n, 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\u00f3n Python 3 instalada.<\/span><\/p>\n<div class=\"responsive-table\">\n<table>\n<tbody>\n<tr>\n<td><b>Mac OS<\/b><br \/>\n(Ejemplo: tu port\u00e1til)<br \/>\n<span style=\"font-weight: 400\">Instalaci\u00f3n directa (pip3 se instala autom\u00e1ticamente):<\/span>(https:\/\/wsvincent.com\/install-python3-mac\/)<\/p>\n<pre class=\"lang:python decode:true\">brew install python3<\/pre>\n<p><span style=\"font-weight: 400\">Configuraci\u00f3n del entorno virtual:<\/span><\/p>\n<pre class=\"lang:sh decode:true\">$ pip3 install virtualenv\r\n$ mkdir ~\/environments\r\n$ virtualenv -p python3 ~\/environments\r\n$ source ~\/environments\/bin\/activate\r\n(environments) jmunta-mac:~ jagadeshmunta\r\n$ python -V\r\nPython 3.7.3\r\n(environments) jmunta-mac:~ jagadeshmunta\r\n<\/pre>\n<p>Instale las bibliotecas necesarias:<\/p>\n<pre class=\"lang:sh decode:true\">$ pip3 install couchbase\r\n$ pip3 install sgmllib3k\r\n$ pip3 install paramiko\r\n$ pip3 install httplib2\r\n$ pip3 install pyyaml\r\n$ pip3 install Geohash\r\n$ pip3 install python-geohash\r\n$ pip3 install deepdiff\r\n$ pip3 install pyes\r\n\r\n<\/pre>\n<p>Por ahora, la siguiente modificaci\u00f3n es necesaria para el cliente http com\u00fan de Python 3, de lo contrario, se producir\u00eda un error.<\/p>\n<pre class=\"lang:sh decode:true\">$ vi \/usr\/lib64\/python3.6\/http\/client.py\u00a0\u00a0 \r\nchunk to chunk.encode() in similar to the below:\r\n1078 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 chunk = f'{len(chunk):X}\\r\\n'.encode('ascii') + chunk.encode() \\<\/pre>\n<p>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td><b>CentOS\u00a0\u00a0<\/b><br \/>\n(<span style=\"font-weight: 400\">Nodo de ejemplo: Jenkins Esclavo)<\/span><br \/>\nConfiguraci\u00f3n directa y entorno virtual:<\/p>\n<pre class=\"lang:sh decode:true\"># yum -y install https:\/\/centos7.iuscommunity.org\/ius-release.rpm\r\n# yum list available &gt; \/tmp\/available_pkgs.txt\r\n# cat \/tmp\/available_pkgs.txt\u00a0 |egrep python3\r\n# yum -y install python36u\r\n# python3.6 --version\r\n# yum -y install python36u-pip\r\n# yum -y install python36u-devel\r\n# python3.6 -V\r\n# mkdir ~\/environments\r\n# cd ~\/environments\/\r\n# python3.6 -m venv my_env\r\n# source ~\/environments\/my_env\/bin\/activate\r\n# python -V<\/pre>\n<p>Instale las bibliotecas necesarias:<\/p>\n<pre class=\"lang:sh decode:true\"># pip3.6 install requests\r\n# pip3.6 install sgmllib3k\r\n# pip3.6 install paramiko\r\n# pip3.6 install httplib2\r\n# pip3.6 install pyyaml\r\n# pip3.6 install pytz\r\n# pip3.6 install Geohash\r\n# pip3.6 install python-geohash\r\n# pip3.6 install deepdiff\r\n# pip3.6 install pyes<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Realiza la instalaci\u00f3n de Couchbase CSDK y Python SDK en el nuevo esclavo:<\/span><\/p>\n<pre class=\"lang:sh decode:true\"># yum -y install wget git\r\n# wget https:\/\/packages.couchbase.com\/releases\/couchbase-release\/couchbase-release-1.0-6-x86_64.rpm\r\n# rpm -iv couchbase-release-1.0-6-x86_64.rpm\r\n# yum install libcouchbase-devel libcouchbase2-bin gcc gcc-c++\r\n# pip3.6 install couchbase<\/pre>\n<p>Por ahora, la siguiente modificaci\u00f3n es necesaria para el cliente http com\u00fan de Python 3, de lo contrario, se producir\u00eda un error.<\/p>\n<pre class=\"lang:sh decode:true\">$ vi \/usr\/lib64\/python3.6\/http\/client.py\u00a0\u00a0 \r\nchunk to chunk.encode() in similar to the below: \r\n1078 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 chunk = f'{len(chunk):X}\\r\\n'.encode('ascii') + chunk.encode() \\<\/pre>\n<p>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td><b>Esclavo Ubuntu utilizando para Python 3 verificaci\u00f3n en tiempo de ejecuci\u00f3n<\/b><br \/>\nInstalaci\u00f3n directa:<\/p>\n<pre class=\"lang:sh decode:true\"># apt install python3-pip<\/pre>\n<p>&nbsp;<\/p>\n<p>Instale las bibliotecas necesarias:<\/p>\n<pre class=\"lang:sh decode:true\"># pip3 install sgmllib3k\r\n# pip3 install paramiko\r\n# pip3 install httplib2\r\n# pip3 install pyyaml\r\n# pip3 install pytz (NOTE: used by xdcr tests)\r\n# pip3 install Geohash\r\n# pip3 install python-geohash\r\n# pip3 install deepdiff\r\n# pip3 install pyes<\/pre>\n<p><span style=\"font-weight: 400\">Instalaci\u00f3n de CSDK y Python SDK: (Ref:<\/span><span style=\"font-weight: 400\">\u00a0<\/span><a href=\"https:\/\/docs.couchbase.com\/c-sdk\/2.10\/start-using-sdk.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/c-sdk\/2.10\/start-using-sdk.html )<\/span><\/a><\/p>\n<pre class=\"lang:sh decode:true\"># wget -O- https:\/\/packages.couchbase.com\/ubuntu\/couchbase.key | sudo apt-key add -\u00a0\r\n# cat \/etc\/apt\/sources.list.d\/couchbase.list\r\ndeb [ arch=amd64 ] https:\/\/packages.couchbase.com\/releases\/couchbase-server\/enterprise\/deb\/ bionic bionic\/main\r\ndeb [ arch=amd64 ] https:\/\/packages.couchbase.com\/releases\/couchbase-server\/community\/deb\/ bionic bionic\/main\r\ndeb https:\/\/packages.couchbase.com\/ubuntu bionic bionic\/main\u00a0\r\n# apt-get update\u00a0\r\n#\u00a0 apt-get install libcouchbase-dev libcouchbase2-bin build-essential\u00a0\r\n#\u00a0 pip3 install couchbase<\/pre>\n<p>Por ahora, la siguiente modificaci\u00f3n es necesaria para el cliente http com\u00fan de Python 3, de lo contrario, se producir\u00eda un error.<\/p>\n<pre class=\"lang:sh decode:true\">$ vi \/usr\/lib64\/python3.6\/http\/client.py\u00a0\u00a0 \r\nchunk to chunk.encode() in similar to the below: \r\n1078 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 chunk = f'{len(chunk):X}\\r\\n'.encode('ascii') + chunk.encode() \\<\/pre>\n<p>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td><b>Windows<\/b><br \/>\n<span style=\"font-weight: 400\">Desc\u00e1rgalo e inst\u00e1lalo: <\/span><a href=\"https:\/\/www.python.org\/ftp\/python\/3.7.4\/python-3.7.4.exe\"><span style=\"font-weight: 400\">https:\/\/www.python.org\/ftp\/python\/3.7.4\/python-3.7.4.exe<\/span><\/a><\/p>\n<pre class=\"lang:ps decode:true\">C:\\Python\\Python37-32&gt;python.exe -VPython 3.7.4\r\nD:\\py3porting\\testrunner&gt;set PATH=C:\\Python\\Python37-32;C:\\Python\\Python37-32\\Scripts;%PATH%\r\nD:\\py3porting\\testrunner&gt;pip3 -V\r\npip 19.0.3 from c:\\python\\python37-32\\lib\\site-packages\\pip (python 3.7)<\/pre>\n<p>Instale las bibliotecas necesarias:<\/p>\n<pre class=\"lang:ps decode:true\">pip3 install libcouchbase\r\npip3 install sgmllib3k\r\npip3 install paramiko\r\npip3 install httplib2\r\npip3 install pyyaml\r\npip3 install Geohash\r\npip3 install python-geohash\r\npip3 install deepdiff\r\npip3 install pyes<\/pre>\n<p>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2><span style=\"font-weight: 400\">Proceso de migraci\u00f3n<\/span><\/h2>\n<p>A grandes rasgos, la portabilidad es un proceso de tres pasos. 1) Conversi\u00f3n autom\u00e1tica 2) Cambios manuales 3) Validaci\u00f3n y correcci\u00f3n en tiempo de ejecuci\u00f3n<\/p>\n<p>Al principio, clone el repositorio original y realice los cambios b\u00e1sicos de conversi\u00f3n autom\u00e1tica. Checkin los cambios como un nuevo repositorio hasta que la conversi\u00f3n completa se hace. De esta manera, los ciclos de regresi\u00f3n actuales pueden ir sin interrupci\u00f3n.<\/p>\n<h3><span style=\"font-weight: 400\">1. Conversi\u00f3n autom\u00e1tica<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Existe una herramienta automatizada llamada <\/span><a href=\"https:\/\/docs.python.org\/2\/library\/2to3.html#\"><span style=\"font-weight: 400\">2a3<\/span><\/a> herramienta<span style=\"font-weight: 400\">proporcionado por el equipo de Python 3, que ayuda a resolver algunos problemas comunes como la impresi\u00f3n, las excepciones, el empaquetado de listas, las importaciones relativas, etc.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Puede empezar con un \u00fanico directorio en el espacio de trabajo clonado localmente para hacer una doble comprobaci\u00f3n. M\u00e1s tarde, la conversi\u00f3n se puede hacer por completo en todo el c\u00f3digo de modo que la portabilidad b\u00e1sica se lleva a cabo.<\/span><\/p>\n<p>A continuaci\u00f3n se muestran algunos ejemplos de comandos de conversi\u00f3n de 2 a 3 en MacOS. En el \u00faltimo comando, observe que se han aplicado todos los modismos. De esta manera, la primera vez que la conversi\u00f3n puede hacerse cargo de los cambios de clave.<\/p>\n<pre class=\"lang:sh decode:true\">(myenv) jmunta-mac:myscripts jagadeshmunta$ 2to3 . -o new -n -w .\r\nhq-mac:testrunner jagadeshmunta$ cd lib; mv lib\/couchbase_helper ..\/couchbase_helper\r\nhq-mac:testrunner jagadeshmunta$ 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma\u00a0 -n -o ~\/p3testrunner_3 -w . |tee ~\/2to3_3.txt\r\nhq-mac:testrunner jagadeshmunta$ time 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma\u00a0 -n -w . |tee ~\/2to3_4.txt\r\n$ 2to3 -f all -f buffer -f idioms -f set_literal -f ws_comma\u00a0 -n -o ~\/p3testrunner_helper -w ..\/couchbase_helper |tee ~\/2to3_helper.txt\r\ncp -R ~\/p3testrunner_helper\/* .<\/pre>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">2. Cambios manuales<\/span><\/h3>\n<p><span style=\"font-weight: 400\">La conversi\u00f3n autom\u00e1tica 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\u00f3n autom\u00e1tica 2to3.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Ejecutar la clase de prueba y ver si hay alg\u00fan error y corregirlo adecuadamente, decidiendo si hay que cambiar de bytes a str o de str a bytes o alg\u00fan problema de tipo\/comparaci\u00f3n en el que haya que corregir el nombre de la clave en la funci\u00f3n ordenada. Se trata de un proceso iterativo hasta que se haya validado todo el tiempo de ejecuci\u00f3n del c\u00f3digo.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Una vez que un patr\u00f3n com\u00fan seguro es claro, entonces usted puede hacer grep y sed para reemplazar a trav\u00e9s de muchos archivos de clase. Si usted no est\u00e1 seguro acerca de otro c\u00f3digo hasta el tiempo de ejecuci\u00f3n, a continuaci\u00f3n, aplazar hasta que la clase de prueba se ejecuta.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Puede haber problemas con librer\u00edas\/m\u00f3dulos de terceros que pueden haber cambiado, hay que buscarlos en la web y utilizarlos adecuadamente.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Aseg\u00farese de que se cubre toda la ruta del c\u00f3digo ejecut\u00e1ndolo en todas las plataformas y par\u00e1metros compatibles.<\/span><\/p>\n<h3>3. Validaci\u00f3n y correcci\u00f3n en tiempo de ejecuci\u00f3n<\/h3>\n<p><span style=\"font-weight: 400\">Una vez realizada la conversi\u00f3n, a continuaci\u00f3n, realizar un mont\u00f3n de tiempo de ejecuci\u00f3n de c\u00f3digo como Python es un lenguaje din\u00e1mico. De lo contrario, los cambios pueden romper las cosas si usted hace s\u00f3lo visual est\u00e1tica de inspecci\u00f3n de c\u00f3digo \/ cambios. Usted puede comenzar con pruebas b\u00e1sicas de sanidad, pruebas de aceptaci\u00f3n y luego seleccionar pruebas completas de un solo m\u00f3dulo de pruebas. <\/span><\/p>\n<p><span style=\"font-weight: 400\">Una vez que se sienta c\u00f3modo, entonces vaya con todos los dem\u00e1s m\u00f3dulos uno por uno. Sigue comprobando los cambios en el nuevo repositorio. Adem\u00e1s, necesitas asegurarte de que no hay regresiones con los cambios portados desde este nuevo repositorio ejecutando pruebas de sanidad en las nuevas compilaciones. Adem\u00e1s, la validaci\u00f3n debe incluir todas las plataformas soportadas con Python 3.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">C\u00f3digo portado de Python 3 y estado<\/span><\/h2>\n<p><span style=\"font-weight: 400\">A continuaci\u00f3n se muestra d\u00f3nde encontrar el nuevo repositorio para el c\u00f3digo 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\u00f3n manual a este.<\/span><\/p>\n<p><a href=\"https:\/\/github.com\/couchbaselabs\/testrunner-py3\/\"><span style=\"font-weight: 400\">https:\/\/github.com\/couchbaselabs\/testrunner-py3\/<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">(Rama: master)<\/span><\/p>\n<p><span style=\"font-weight: 400\">Muchos cambios comunes ya se han realizado pero no se han completado, ya que puede haber otros problemas en tiempo de ejecuci\u00f3n. Las correcciones en com\u00fan tambi\u00e9n pueden retroceder a las correcciones anteriores debido a las suposiciones sobre las conversiones del tipo de valor de entrada. A\u00fan queda c\u00f3digo portado por validar con Python 3 y el esfuerzo sigue en marcha.<\/span><\/p>\n<p>Ahora, perm\u00edtanme mostrarles los problemas comunes <span style=\"font-weight: 400\">que ocurri\u00f3<\/span> durante la validaci\u00f3n en tiempo de ejecuci\u00f3n. Usted puede utilizar esto como una referencia cuando usted golpea un problema para ver si usted est\u00e1 teniendo el problema similar. Usted puede aplicar la misma soluci\u00f3n y ver si funciona para usted. <span style=\"font-weight: 400\">Y si tienes alguna<\/span> nuevas ideas, puedes ponerlas en los comentarios.<\/p>\n<h2><span style=\"font-weight: 400\">Problemas comunes en tiempo de ejecuci\u00f3n<\/span><\/h2>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">1. Problema(s): <\/span><\/h4>\n<ul>\n<li><span style=\"font-weight: 400\">Es posible que se produzcan algunos de los siguientes TypeErrors durante la ejecuci\u00f3n, como str en lugar de bytes y bytes en lugar de str<\/span><\/li>\n<li><span style=\"font-weight: 400\">Error#1. TypeError: can't concat str to bytes<\/span><\/li>\n<li><span style=\"font-weight: 400\">Error#2. TypeError: debe ser str, no bytes<\/span>\n<ul>\n<li>\n<pre class=\"lang:python decode:true\">File \"lib\/mc_bin_client.py\", line 53, in __init__&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nif msg: supermsg += \":&amp;nbsp; \" + str(msg)\r\nTypeError: must be str, not bytes\r\n\r\nFile \"lib\/mc_bin_client.py\", line 141, in _recvMsg\u00a0\u00a0\u00a0\u00a0\r\nresponse += data\r\nTypeError: must be str, not bytes<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"font-weight: 400\">Error#3. TypeError: se requiere un objeto tipo bytes, no 'str'.<\/span>\n<ul>\n<li>\n<pre class=\"lang:python decode:true\">File \"lib\/remote\/remote_util.py\", line 3038, in log_command_output&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nif \"Warning\" in line and \"hugepages\" in line:\r\nTypeError: a bytes-like object is required, not 'str'\r\n\r\nFile \"lib\/tasks\/task.py\", line 1167, in run_high_throughput_mode&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nraise Exception(rv[\"err\"])\r\nException: a bytes-like object is required, not 'str'\r\n\r\nFile \"lib\/mc_bin_client.py\", line 936, in _set_vbucket&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nself.vbucketId = (((zlib.crc32(key)) &gt;&gt; 16) &amp; 0x7fff) &amp; (self.vbucket_count - 1)\r\nTypeError: a bytes-like object is required, not 'str'\r\n\r\n\r\nFile \"lib\/mc_bin_client.py\", line 148, in _recvMsg\u00a0\u00a0\u00a0\u00a0\r\nmagic = struct.unpack(\"&gt;B\", response[0:1])[0]\r\nTypeError: a bytes-like object is required, not 'str'\r\n\r\nFile \"lib\/remote\/remote_util.py\", line 4560, in check_cmd&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nif out and command_output in out[0]:\r\nTypeError: a bytes-like object is required, not 'str'\r\n<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"font-weight: 400\">Error#4. TypeError: No se pueden mezclar argumentos str y no str<\/span>\n<ul>\n<li>\n<pre class=\"lang:python decode:true\">File \"lib\/mc_bin_client.py\", line 126, in _sendMsg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nself.s.send(msg + extraHeader + key + val + extended_meta_data)\r\nTypeError: can't concat str to bytes\r\n\r\nFile \"\/usr\/lib64\/python3.6\/urllib\/parse.py\", line 120, in _coerce_args\u00a0\u00a0\u00a0\u00a0\r\nraise TypeError(\"Cannot mix str and non-str arguments\")\r\nTypeError: Cannot mix str and non-str arguments<\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">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<\/span><\/p>\n<h4><span style=\"font-weight: 400\"><br \/>\n<\/span><span style=\"font-weight: 400\">2. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">TypeError: <\/span><span style=\"font-weight: 400\">root - ERROR - ---&gt;instalaci\u00f3n fallida: se requiere un objeto tipo bytes, no 'str'<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):\u00a0 <\/span><\/h4>\n<p><span style=\"font-weight: 400\">En este caso, a\u00f1ada b como prefijo a la cadena objeto de comparaci\u00f3n o cambie el tipo byte por el tipo cadena. Ejemplo: lib\/remote\/remote_util.py<\/span><\/p>\n<pre class=\"lang:python decode:true\">if o[0] != b\"\":\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   o = o[0].split(b\" \")<\/pre>\n<p><span style=\"font-weight: 400\">Rodea con try-except para comprobar la l\u00ednea exacta que causa el error (digamos por encima de TypeError.)\u00a0<\/span><\/p>\n<pre class=\"lang:python decode:true\">\u00a0import traceback\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n try:\u00a0\u00a0\r\n \r\n ..\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n \r\n except Exception as e:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   log.info(\"{}\".format(e))\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   traceback.print_exc()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   exc_type, exc_obj, exc_tb = sys.exc_info()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n   print(exc_type, fname, exc_tb.tb_lineno)<\/pre>\n<p><span style=\"font-weight: 400\">Ejemplo de salida despu\u00e9s de traceback.print_exec() para ver el stack trace completo en similar a java.<\/span><\/p>\n<p>Arreglar con cambios a lib\/remote\/remote_util.py como abajo.<\/p>\n<pre class=\"lang:python decode:true\">\u00a0\u00a0\u00a0\r\n3079 \u00a0 \u00a0 \u00a0 \u00a0 for line in output:\u00a0\u00a0\u00a0\r\n3080\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0try:\u00a0\u00a0\u00a0\r\n3081 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 line=line.decode()\u00a0\u00a0\u00a0\r\n3082 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 except AttributeError:\u00a0\u00a0\u00a0\r\n3083 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 pass<\/pre>\n<h4><\/h4>\n<h4><span style=\"font-weight: 400\">3. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">File \"lib\/membase\/api\/rest_client.py\", line 4178, in multiscan_count_for_gsi_index_with_rest&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\ncontent = content.split(\"[]\")[0]\r\nTypeError: a bytes-like object is required, not 'str'<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<pre class=\"lang:python decode:true\">content = content.split(b'[]')[0].decode()<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">4. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">AttributeError falta suite_setUp() o suite_tearDown() en algunos testsuites.<\/span><\/p>\n<pre class=\"lang:python decode:true\">AttributeError: type object 'XDCRAdvFilterTests' has no attribute 'suite_setUp'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">A\u00f1ade los m\u00e9todos ficticios suite_setUp() y suite_tearDown().\u00a0<\/span><\/p>\n<pre class=\"lang:sh decode:true\">11a12,18\r\n&gt; \r\n&gt;     def suite_setUp(self):\r\n&gt;         print(\"*** XDCRAdvFilterTests : suite_Setup() ***\")\r\n&gt; \r\n&gt;     def suite_tearDown(self):\r\n&gt;         print(\"*** XDCRAdvFilterTests : suite_tearDown() ***\")\r\n&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">5. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">File \".\/testrunner.py\", line 416, in main\u00a0\u00a0\u00a0\u00a0\r\nresult.errors = [(name, e.message)]\r\nAttributeError: 'AttributeError' object has no attribute 'message'<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">result.errors = [(name, str(e))]<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">6. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">AttributeError: 'Transport' object has no attribute '_Thread__stop'<\/span><\/p>\n<pre class=\"lang:python decode:true\">File \".\/testrunner.py\", line 529, in main&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nt._Thread__stop()\r\nAttributeError: 'Transport' object has no attribute '_Thread__stop'\r\n\r\nFile \"pytests\/view\/viewquerytests.py\", line 45, in stop\u00a0\u00a0\u00a0\u00a0\r\nself._Thread__stop()\r\nAttributeError: 'StoppableThread' object has no attribute '_Thread__stop'\u00a0\u00a0\u00a0\u00a0\r\n\r\nself._stop()\r\nTypeError: 'Event' object is not callable\r\n<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">No hay parada directa de un hilo no daem\u00f3nico. Pero sint\u00e1cticamente se puede usar t._stop(). La recomendaci\u00f3n es usar el graceful shutdown usando una bandera global y comprobar en el run() del hilo para romper.<\/span><\/p>\n<p><span style=\"font-weight: 400\">(<\/span><a href=\"https:\/\/stackoverflow.com\/questions\/27102881\/python-threading-self-stop-event-object-is-not-callable\"><span style=\"font-weight: 400\">https:\/\/stackoverflow.com\/questions\/27102881\/python-threading-self-stop-event-object-is-not-callable<\/span><\/a><span style=\"font-weight: 400\">)<\/span><\/p>\n<h3><\/h3>\n<h4><span style=\"font-weight: 400\">7. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">No se encontr\u00f3 la prueba expirytests.ExpiryTests.test_expired_keys: el m\u00f3dulo 'string' no tiene el atributo 'translate'.<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Reescribir con m\u00e9todos est\u00e1ticos str. No hay forma antigua de obtener todos los chars, as\u00ed que usamos el c\u00f3digo anterior y usamos total set.<\/span><\/p>\n<p><span style=\"font-weight: 400\">vi lib\/membase\/api\/tap.py\u00a0<\/span><\/p>\n<pre class=\"lang:python decode:true\">def buildGoodSet(goodChars=string.printable, badChar='?'):\u00a0\u00a0\u00a0\u00a0\r\n143 \u00a0 \u00a0 \"\"\"Build a translation table that turns all characters not in goodChars\u00a0\u00a0\u00a0\u00a0\r\n144 \u00a0 \u00a0 to badChar\"\"\"\u00a0\u00a0\u00a0\u00a0\r\n145 \u00a0 \u00a0 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 !\"#$%&amp;\\'()*+,-.\/0123\u00a0 \u00a0 \u00a0 \u00a0 456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x9 \u00a0 \u00a0 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\\\u00a0 \u00a0 \u00a0 \u00a0 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'\u00a0\u00a0\u00a0\u00a0\r\n146 \u00a0 \u00a0 badchars = str.maketrans(allChars, allChars, goodChars)\u00a0\u00a0\u00a0\u00a0\r\n147 \u00a0 \u00a0 badchars1=str.translate(allChars,badchars)\u00a0\u00a0\u00a0\u00a0\r\n148 \u00a0 \u00a0 rv = str.maketrans(badchars1, badChar * len(badchars1))\u00a0\u00a0\u00a0\u00a0\r\n149 \u00a0 \u00a0 return rv<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">8. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">TabError: uso incoherente de tabuladores y espacios en la sangr\u00eda<\/span><\/p>\n<pre class=\"lang:python decode:true\">File \"pytests\/security\/audittest.py\", line 396\u00a0\u00a0\u00a0\u00a0\r\nshell = RemoteMachineShellConnection(self.master)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n^\r\nTabError: inconsistent use of tabs and spaces in indentation<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Buscar caracteres de tabulaci\u00f3n y sustituirlos por caracteres de espacio.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Para el problema anterior, elimine los caracteres de tabulaci\u00f3n.<\/span><\/p>\n<pre class=\"lang:sh decode:true\">sed -i 's\/\\t\/\u00a0 \u00a0 \u00a0 \u00a0 \/g' pytests\/security\/audittest.py<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">9. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">File \"lib\/couchbase_helper\/documentgenerator.py\", line 83, in __next__\u00a0\u00a0\u00a0\u00a0\r\nvalue = arg[seed % len(arg)]\r\nTypeError: list indices must be integers or slices, not float\r\n\r\nFile \"lib\/membase\/helper\/bucket_helper.py\", line 517, in load_some_data\u00a0\u00a0\u00a0\u00a0\r\nkeys = [\"key_%s_%d\" % (testuuid, i) for i in range(number_of_buckets)]\r\nTypeError: 'float' object cannot be interpreted as an integer\u00a0\r\n\r\nFile \"lib\/membase\/helper\/bucket_helper.py\", line 372, in verify_data\u00a0\u00a0\u00a0\u00a0\r\ntest.assertEqual(value, key, msg='values dont match')\r\nAssertionError: b'key_d918f450-5858-4430-a016-230e1f45bcf9_0' != 'key_d918f450-5858-4430-a016-230e1f45bcf9_0' : values dont match\r\n\r\nFile \"pytests\/setgettests.py\", line 90, in set_get_test\u00a0\u00a0\u00a0\u00a0\r\nself.test.fail(\"value mismatch for key {0}\".format(key))\r\nAssertionError: value mismatch for key 9fcbd36f-e34d-477b-9fc5-0a5d067dff4b\r\n\r\nFile \"pytests\/security\/auditmain.py\", line 320, in returnFieldsDef\u00a0\u00a0\u00a0\u00a0\r\nif (isinstance((particulars['mandatory_fields'][items.encode('utf-8')]), dict)):\r\nKeyError: b'bucket_name'\r\n\r\nFile \"lib\/tasks\/task.py\", line 2370, in _check_ddoc_revision\u00a0\u00a0\u00a0\u00a0\r\nnew_rev_id = self._parse_revision(meta['rev'])\r\nKeyError: 'rev'\r\n<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Problema de sensibilidad a may\u00fasculas y min\u00fasculas. Corregido cambiando de clave x_couchbase_meta a X_Couchbase_Meta.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">10. Problema(s): <\/span><\/h4>\n<ul>\n<li><span style=\"font-weight: 400\">Error#1. TypeError: '&lt;&#039; no soportado entre instancias de &#039;dict&#039; y &#039;dict&#039;.<\/span><\/li>\n<li><span style=\"font-weight: 400\">Error#2. TypeError: 'cmp' es un argumento de palabra clave no v\u00e1lido para esta funci\u00f3n<\/span><\/li>\n<\/ul>\n<pre class=\"lang:python decode:true\">File \"pytests\/tuqquery\/tuq_dml.py\", line 455, in test_insert_with_select\u00a0\u00a0\u00a0\u00a0\r\nexpected_result = sorted([{bucket.name: {'name': doc['name']}} for doc in values[:num_docs]])\r\nTypeError: '&lt;' not supported between instances of 'dict' and 'dict'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">expected_result = sorted(expected_result,key=(lambda x: x[bucket.name]['name']))<\/pre>\n<p><span style=\"font-weight: 400\">\u00a0\u00a0\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">11. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">File \"pytests\/tuqquery\/tuq_2i_index.py\", line 1057, in test_simple_array_index\u00a0\u00a0\u00a0\u00a0\r\nself.assertTrue(sorted(actual_result_within['results']) == sorted(expected_result['results']))\r\nTypeError: '&lt;' not supported between instances of 'dict' and 'dict'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<pre class=\"lang:default decode:true\">-\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self.assertTrue(sorted(actual_result_within['results']) == sorted(expected_result['results']))\r\n+\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self.assertTrue(sorted(actual_result_within['results'], key=(lambda x: x['name'])) == \\\r\n+\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sorted(expected_result['results'], key=(lambda x: x['name'])))<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">12. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">File \"pytests\/tuqquery\/tuq.py\", line 1221, in _verify_results&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\r\nself.fail(\"Results are incorrect.Actual num %s. Expected num: %s.\\n\" % (len(actual_result), len(expected_result)))\r\nAssertionError: Results are incorrect.Actual num 0. Expected num: 72.\r\n\r\nFile \"lib\/tasks\/task.py\", line 3638, in filter_emitted_rows\u00a0\u00a0\u00a0\u00a0\r\nreverse=descending_set)\r\nTypeError: 'cmp' is an invalid keyword argument for this function<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">expected_rows = sorted(self.emitted_rows, key=(lambda x: (x['key'],x['id'])),reverse=descending_set)<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">13. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">\u00a0File \"lib\/tasks\/task.py\", line 3675, in &lt;listcomp&gt;\u00a0\u00a0\u00a0\u00a0\r\nexpected_rows = [row for row in expected_rows if row['key'] &gt;= start_key and row['key'] &lt;= end_key]\r\nTypeError: '&gt;=' not supported between instances of 'int' and 'NoneType'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Aqu\u00ed, deber\u00eda devolver int ya que python 3 no compara autom\u00e1ticamente como en python 2.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">14. Problema(s): <\/span><\/h4>\n<pre class=\"lang:python decode:true\">hasattr(items,\u2019iteritems\u2019) doesn\u2019t return true<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">@@ -754,7 +755,7 @@ class MemcachedClient(object):\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n# If this is a dict, convert it to a pair generator\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\ncollection = self.collection_name(collection)\u00a0\r\n-\u00a0 \u00a0 \u00a0 \u00a0 if hasattr(items, 'iteritems'):\r\n+\u00a0 \u00a0 \u00a0 \u00a0 if hasattr(items, 'items'):\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nitems = iter(items.items())\r\n\r\nif hasattr(items, 'items'):<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">15. Problema(s):<\/span><\/h4>\n<pre class=\"lang:python decode:true\">\u00a0File \"lib\/crc32.py\", line 78, in crc32_hash\u00a0\u00a0\u00a0\u00a0\r\ncrc = (crc &gt;&gt; 8) ^ crc32tab[int((crc ^ ord(ch)) &amp; 0xff)]\r\nTypeError: ord() expected string of length 1, but int found<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Convierte la clave a cadena para que ch sea cadena en lugar de int con clave binaria. Ver el archivo.<\/span><\/p>\n<pre class=\"lang:python decode:true\">try:\u00a0\r\n  key = key.decode()\r\nexcept \r\n  AttributeError:\u00a0pass<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">16. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">TypeError: El objeto 'FileNotFoundError' no es sub-scriptible<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Cambiado en Python 3 como FileNotFoundError no es sub-scriptable y en su lugar, utilizar el atributo errno, e.errno<\/span><\/p>\n<pre class=\"lang:python decode:true\">File \"lib\/remote\/remote_util.py\", line 1714, in create_directory\u00a0\u00a0\u00a0\u00a0\r\nif e[0] == 2:\r\nTypeError: 'FileNotFoundError' object is not subscriptable\r\n-\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if e[0] == 2:\r\n+\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if e.errno == 2:<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">17. Problema(s): <\/span><\/h4>\n<pre class=\"lang:python decode:true\">Traceback (most recent call last):\u00a0\u00a0\r\nFile \"lib\/couchbase_helper\/tuq_helper.py\", line 521, in run_query_and_verify_result\u00a0\u00a0\u00a0\u00a0\r\nself._verify_results(sorted_actual_result, sorted_expected_result)\u00a0\u00a0\r\nFile \"lib\/couchbase_helper\/tuq_helper.py\", line 114, in _verify_results\u00a0\u00a0\u00a0\u00a0\r\nraise Exception(msg)\r\nException: The number of rows match but the results mismatch, please check<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">La comparaci\u00f3n diccionario\/lista anidada no funcionaba debido a que la funci\u00f3n sorted anterior para ordenar completamente ahora no est\u00e1 disponible. Utilice el m\u00f3dulo deepdiff y la clase DeepDiff para realizar la comparaci\u00f3n<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">18. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">AttributeError: module 'string' has no attribute 'replace'<\/span><\/p>\n<pre class=\"lang:default decode:true\">File \"scripts\/populateIni.py\", line 52, in main\u00a0\u00a0\u00a0\u00a0\r\ndata[i] = string.replace(data[i], 'dynamic', servers[0])\r\nAttributeError: module 'string' has no attribute 'replace'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Utilice la variable str directa para reemplazar como se muestra a continuaci\u00f3n para solucionar el problema.<\/span><\/p>\n<pre class=\"lang:python decode:true\">data[i].replace( 'dynamic', servers[0])<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">19. Problema(s): <\/span><\/h4>\n<pre class=\"lang:python decode:true\">TypeError: '&gt;' not supported between instances of 'int' and 'str'<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Utilice la funci\u00f3n str o int adecuadamente.<\/span><\/p>\n<pre class=\"lang:python decode:true\">\u00a0\u00a0if where_clause:\r\n+\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 where_clause = where_clause.replace('if\u00a0 t &gt; \"', 'if str(t) &gt; \"') # to fix the type error between int, str comparison<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">20. Problema(s): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">NameError: el nombre 'cmp' no est\u00e1 definido<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Utiliza el m\u00f3dulo deepdiff y la clase DeepDiff para comparar objetos.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4>21. Problema(s):<\/h4>\n<pre class=\"lang:python decode:true\">\u00a0\u00a0File \"lib\/couchbase_helper\/tuq_helper.py\", line 782, in verify_indexes_redistributed\u00a0\u00a0\u00a0\u00a0\r\nif cmp(items_count_before_rebalance, items_count_after_rebalance) != 0:\r\nNameError: name 'cmp' is not defined<\/pre>\n<h4><span style=\"font-weight: 400\">Soluci\u00f3n(es): <\/span><\/h4>\n<pre class=\"lang:python decode:true\">Use deepdiff module and DeepDiff class to do object comparison.\r\n-\u00a0 \u00a0 \u00a0 \u00a0 if cmp(index_state_before_rebalance, index_state_after_rebalance) != 0:\r\n+\u00a0 \u00a0 \u00a0 \u00a0 if DeepDiff(index_state_before_rebalance, index_sFile \"lib\/couchbase_helper\/documentgenerator.py\", line 19, in has_next\u00a0\u00a0\u00a0\u00a0\r\nreturn self.itr &lt; self.end\r\nTypeError: '&lt;' not supported between instances of 'int' and 'str'<\/pre>\n<p><span style=\"font-weight: 400\">Convierta str a int como se indica a continuaci\u00f3n para el problema de error de tipo anterior.<\/span><\/p>\n<pre class=\"lang:python decode:true\">return int(self.itr) &lt; int(self.end)<\/pre>\n<p>&#8212;-<\/p>\n<p>Esto es todo por ahora en la lista de problemas a tener en cuenta cuando actualices Python versi\u00f3n 2 a Python versi\u00f3n 3. Publicaremos m\u00e1s aprendizajes en futuras entradas del blog. Mientras tanto, \u00a1buena suerte con la migraci\u00f3n!<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Otras lecturas<\/span><\/h2>\n<p>Las siguientes referencias nos ayudaron. Tambi\u00e9n puede leer m\u00e1s en los siguientes enlaces de referencia para obtener m\u00e1s detalles y mejorar su c\u00f3digo de portar a Python 3.<\/p>\n<ol>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0373\/\"><span style=\"font-weight: 400\">https:\/\/www.python.org\/dev\/peps\/pep-0373\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/wiki.python.org\/moin\/Python2orPython3\"><span style=\"font-weight: 400\">https:\/\/wiki.python.org\/moin\/Python2orPython3<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/www.toptal.com\/python\/python-3-is-it-worth-the-switch\"><span style=\"font-weight: 400\">https:\/\/www.toptal.com\/python\/python-3-is-it-worth-the-switch<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/weknowinc.com\/blog\/running-multiple-python-versions-mac-osx\"><span style=\"font-weight: 400\">https:\/\/weknowinc.com\/blog\/running-multiple-python-versions-mac-osx<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.python.org\/3\/howto\/pyporting.html\"><span style=\"font-weight: 400\">https:\/\/docs.python.org\/3\/howto\/pyporting.html<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/wsvincent.com\/install-python3-mac\/\"><span style=\"font-weight: 400\">https:\/\/wsvincent.com\/install-python3-mac\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/python3porting.com\/pdfs\/SupportingPython3-screen-1.0-latest.pdf\"><span style=\"font-weight: 400\">https:\/\/python3porting.com\/pdfs\/SupportingPython3-screen-1.0-latest.pdf<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/riptutorial.com\/Download\/python-language.pdf\"><span style=\"font-weight: 400\">https:\/\/riptutorial.com\/Download\/python-language.pdf<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/python-sdk\/2.5\/start-using-sdk.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/python-sdk\/2.5\/start-using-sdk.html<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/c-sdk\/2.10\/start-using-sdk.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/c-sdk\/2.10\/start-using-sdk.html<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/pypi.org\/project\/deepdiff\/\"><span style=\"font-weight: 400\">https:\/\/pypi.org\/project\/deepdiff\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/buildmedia.readthedocs.org\/media\/pdf\/portingguide\/latest\/portingguide.pdf\"><span style=\"font-weight: 400\">https:\/\/buildmedia.readthedocs.org\/media\/pdf\/portingguide\/latest\/portingguide.pdf<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/ptgmedia.pearsoncmg.com\/imprint_downloads\/informit\/promotions\/python\/python2python3.pdf\"><span style=\"font-weight: 400\">https:\/\/ptgmedia.pearsoncmg.com\/imprint_downloads\/informit\/promotions\/python\/python2python3.pdf<\/span><\/a><\/li>\n<\/ol>\n<p>Espero que hayan pasado un buen rato leyendo.<\/p>\n<p><strong>Descargo de responsabilidad:<\/strong> Por favor, vea esto como una referencia r\u00e1pida para su actualizaci\u00f3n a Python 3, m\u00e1s que como una gu\u00eda completa para resolver problemas de portabilidad. Nuestra intenci\u00f3n aqu\u00ed es ayudarte en alg\u00fan nivel y darte un empuj\u00f3n en el proceso de portabilidad. Por favor, si\u00e9ntete libre de compartir si has aprendido algo nuevo que pueda ayudarnos. Agradecemos sus comentarios positivos.<\/p>\n<p>&nbsp;<\/p>\n<p>&#8212;<\/p>\n<p>Gracias a Raju Suravarjjala y Keshav Murthy por sus aportaciones y comentarios clave.<\/p>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction The last major Python upgrade &#8212; to version 3 &#8212; arrived in Dec. 2008, nearly 12 years ago. And yet there is a good chance that you are still working on the Python 2 product or test code. If [&hellip;]<\/p>","protected":false},"author":46261,"featured_media":9922,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,2381,1816,9139,2389],"tags":[1725],"ppma_author":[9096],"class_list":["post-7726","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-community","category-couchbase-server","category-python","category-solutions","tag-nosql-database"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Python 2 to 3 Migration: How to Update &amp; Key Differences<\/title>\n<meta name=\"description\" content=\"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Update Python 2 to Python 3 &amp; The Differences Between Them\" \/>\n<meta property=\"og:description\" content=\"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-13T21:34:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:25:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1575\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jagadesh Munta, Principal Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jagadesh Munta, Principal Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\"},\"author\":{\"name\":\"Jagadesh Munta, Principal Software Engineer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5efab7fca2a650b389d487e721997306\"},\"headline\":\"How to Update Python 2 to Python 3 &amp; The Differences Between Them\",\"datePublished\":\"2019-10-13T21:34:34+00:00\",\"dateModified\":\"2025-06-14T04:25:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\"},\"wordCount\":2541,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg\",\"keywords\":[\"NoSQL Database\"],\"articleSection\":[\"Best Practices and Tutorials\",\"Community\",\"Couchbase Server\",\"Python\",\"Solutions\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\",\"name\":\"Python 2 to 3 Migration: How to Update & Key Differences\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg\",\"datePublished\":\"2019-10-13T21:34:34+00:00\",\"dateModified\":\"2025-06-14T04:25:16+00:00\",\"description\":\"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg\",\"width\":1575,\"height\":628,\"caption\":\"Developers discuss how to upgrade python.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Update Python 2 to Python 3 &amp; The Differences Between Them\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5efab7fca2a650b389d487e721997306\",\"name\":\"Jagadesh Munta, Principal Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/2b547f1e03e58f24f78d6318913302d1\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6d1189147482e8a4e1c0d2a3db919014c2cfe816b6d11357c3fd740f9deadd31?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6d1189147482e8a4e1c0d2a3db919014c2cfe816b6d11357c3fd740f9deadd31?s=96&d=mm&r=g\",\"caption\":\"Jagadesh Munta, Principal Software Engineer, Couchbase\"},\"description\":\"Jagadesh Munta is a Principal Software Engineer at Couchbase Inc. USA. Prior to this, he was a veteran in Sun Microsystems and Oracle together for 19 years. Jagadesh is holding Masters in Software Engineering at San Jose State University,USA and B.Tech. Computer Science and Engineering at JNTU,India. He is an author of \\\"Software Quality and Java Automation Engineer Survival Guide\u201d to help Software developers and Quality automation engineers.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/jagadesh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Python 2 to 3 Migration: How to Update & Key Differences","description":"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","og_locale":"es_MX","og_type":"article","og_title":"How to Update Python 2 to Python 3 &amp; The Differences Between Them","og_description":"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","og_site_name":"The Couchbase Blog","article_published_time":"2019-10-13T21:34:34+00:00","article_modified_time":"2025-06-14T04:25:16+00:00","og_image":[{"width":1575,"height":628,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg","type":"image\/jpeg"}],"author":"Jagadesh Munta, Principal Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jagadesh Munta, Principal Software Engineer, Couchbase","Est. reading time":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/"},"author":{"name":"Jagadesh Munta, Principal Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5efab7fca2a650b389d487e721997306"},"headline":"How to Update Python 2 to Python 3 &amp; The Differences Between Them","datePublished":"2019-10-13T21:34:34+00:00","dateModified":"2025-06-14T04:25:16+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/"},"wordCount":2541,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg","keywords":["NoSQL Database"],"articleSection":["Best Practices and Tutorials","Community","Couchbase Server","Python","Solutions"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","url":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","name":"Python 2 to 3 Migration: How to Update & Key Differences","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg","datePublished":"2019-10-13T21:34:34+00:00","dateModified":"2025-06-14T04:25:16+00:00","description":"Learn how to update from Python 2 to 3 in this post from Couchbase. We also cover their key differences and identify common problems with migration.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/10\/update-python-blogbanner.jpg","width":1575,"height":628,"caption":"Developers discuss how to upgrade python."},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to Update Python 2 to Python 3 &amp; The Differences Between Them"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5efab7fca2a650b389d487e721997306","name":"Jagadesh Munta, Ingeniero Principal de Software, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/2b547f1e03e58f24f78d6318913302d1","url":"https:\/\/secure.gravatar.com\/avatar\/6d1189147482e8a4e1c0d2a3db919014c2cfe816b6d11357c3fd740f9deadd31?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6d1189147482e8a4e1c0d2a3db919014c2cfe816b6d11357c3fd740f9deadd31?s=96&d=mm&r=g","caption":"Jagadesh Munta, Principal Software Engineer, Couchbase"},"description":"Jagadesh Munta es Ingeniero Principal de Software en Couchbase Inc. EE.UU. Anteriormente, trabaj\u00f3 en Sun Microsystems y Oracle durante 19 a\u00f1os. Jagadesh tiene un m\u00e1ster en Ingenier\u00eda de Software por la Universidad Estatal de San Jos\u00e9 (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\u00f3n de la calidad.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/jagadesh\/"}]}},"authors":[{"term_id":9096,"user_id":46261,"is_guest":0,"slug":"jagadesh","display_name":"Jagadesh Munta, Principal Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/6d1189147482e8a4e1c0d2a3db919014c2cfe816b6d11357c3fd740f9deadd31?s=96&d=mm&r=g","first_name":"Jagadesh","last_name":"Munta, Principal Software Engineer, Couchbase","user_url":"","author_category":"","description":"Jagadesh Munta es Ingeniero Principal de Software en Couchbase Inc. EE.UU. Anteriormente, trabaj\u00f3 en Sun Microsystems y Oracle durante 19 a\u00f1os. Jagadesh tiene un m\u00e1ster en Ingenier\u00eda de Software por la Universidad Estatal de San Jos\u00e9 (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\u00f3n de la calidad."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/7726","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/46261"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=7726"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/7726\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/9922"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=7726"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=7726"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=7726"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=7726"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}