{"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\/pt\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","title":{"rendered":"Como atualizar o Python 2 para o Python 3 e as diferen\u00e7as entre eles"},"content":{"rendered":"<h2><span style=\"font-weight: 400\">Introdu\u00e7\u00e3o<\/span><\/h2>\n<p><span style=\"font-weight: 400\">A \u00faltima grande atualiza\u00e7\u00e3o do Python - para a vers\u00e3o 3 - ocorreu em dezembro de 2008, h\u00e1 quase 12 anos. No entanto, h\u00e1 uma boa chance de que voc\u00ea ainda esteja trabalhando no produto Python 2 ou no c\u00f3digo de teste. Nesse caso, voc\u00ea pode estar vendo a mensagem de deprecia\u00e7\u00e3o abaixo como um lembrete para atualizar a vers\u00e3o do Python com a qual est\u00e1 trabalhando.<\/span><\/p>\n<p><span style=\"font-weight: 400\">\"DEPRECATION: O Python 2.7 chegar\u00e1 ao fim de sua vida \u00fatil em 1\u00ba de janeiro de 2020. Atualize seu Python, pois o Python 2.7 n\u00e3o ser\u00e1 mantido ap\u00f3s essa data. Uma vers\u00e3o futura do pip deixar\u00e1 de oferecer suporte ao Python 2.7.\"<\/span><\/p>\n<p><span style=\"font-weight: 400\">Leve isso a s\u00e9rio e planeje adequadamente: As atualiza\u00e7\u00f5es do Python para a vers\u00e3o 3.x n\u00e3o s\u00e3o compat\u00edveis com vers\u00f5es anteriores. O que voc\u00ea escreve com as vers\u00f5es 2.x do Python pode n\u00e3o funcionar corretamente quando usar a 3.x<\/span><span style=\"font-weight: 400\">.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400\">N\u00e3o deixe de ler tamb\u00e9m as letras mi\u00fadas. De acordo com o site da linguagem de programa\u00e7\u00e3o, a data final de lan\u00e7amento da atualiza\u00e7\u00e3o do Python ainda \u00e9 uma inc\u00f3gnita: \"Por ser a \u00faltima da s\u00e9rie 2.x, a vers\u00e3o 2.7 receber\u00e1 suporte para corre\u00e7\u00e3o de bugs at\u00e9 2020. O suporte ser\u00e1 oficialmente interrompido em 1\u00ba de janeiro de 2020, mas a vers\u00e3o final ocorrer\u00e1 ap\u00f3s essa data.\" [<a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0373\/#update\">1<\/a>]<\/span><\/p>\n<p><span style=\"font-weight: 400\">Portanto, o Python 2 entrar\u00e1 no modo sem suporte at\u00e9 o final deste ano. Se voc\u00ea ainda n\u00e3o tiver feito isso, agora \u00e9 um bom momento para migrar o c\u00f3digo atual do Python 2 para a sintaxe do Python 3 e manter o Python 3 daqui para frente. <\/span><\/p>\n<p><span style=\"font-weight: 400\">Por que as equipes simplesmente n\u00e3o iniciam essa migra\u00e7\u00e3o do Python 2 para o 3? Um dos principais obst\u00e1culos \u00e9 que a maioria dos c\u00f3digos funcionais simplesmente quebra (leia mais em <\/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\">why-was-python-3-made-incompatible-with-python-2<\/span><\/a><span style=\"font-weight: 400\">), seja por causa da sintaxe direta da linguagem ou por problemas com APIs de terceiros. Sejamos justos: poucos de n\u00f3s se preocupariam com a migra\u00e7\u00e3o se as novas atualiza\u00e7\u00f5es do Python fossem compat\u00edveis com as vers\u00f5es anteriores. Em vez disso, a vers\u00e3o 2 ficar\u00e1 sem suporte, for\u00e7ando muitos - inclusive n\u00f3s aqui no Couchbase - a priorizar a migra\u00e7\u00e3o. Mesmo que a equipe ultrapasse o prazo de suporte para corre\u00e7\u00e3o de bugs, n\u00e3o h\u00e1 problema (porque seu c\u00f3digo ainda est\u00e1 funcionando). Como equipe, decidimos que \u00e9 melhor migrar o mais pr\u00f3ximo poss\u00edvel dessa data para que possamos estar na mesma p\u00e1gina que outros membros da comunidade Python e aprender com eles.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Este documento \u00e9 uma cole\u00e7\u00e3o de dicas e truques que aprendemos durante a atualiza\u00e7\u00e3o para o Python 3, juntamente com problemas comuns que encontramos durante o processo de migra\u00e7\u00e3o da infraestrutura de teste do Couchbase. Como voc\u00ea ver\u00e1, atualizamos o Python manualmente pela linha de comando depois de iniciarmos um processo automatizado. Sua abordagem pode ser diferente. Independentemente disso, comece assim que puder. A atualiza\u00e7\u00e3o do python da vers\u00e3o 2 para a vers\u00e3o 3 \u00e9 importante.<\/span><\/p>\n<p><a href=\"https:\/\/www.couchbase.com\/blog\/pt\/downloads\/\"><span style=\"font-weight: 400\">Couchbase<\/span><\/a><span style=\"font-weight: 400\"> \u00e9 um banco de dados NoSQL de classe empresarial de c\u00f3digo aberto, do MultiCloud ao Edge. A estrutura de teste funcional do Couchbase, TestRunner, foi desenvolvida em Python 2. O reposit\u00f3rio git do TestRunner pode ser encontrado em<\/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\"> .  Nosso objetivo agora \u00e9 mudar completamente para o tempo de execu\u00e7\u00e3o do Python 3 em vez de executar conjuntamente o Python 3 e o Python 2.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Como parte do processo de atualiza\u00e7\u00e3o do Python, identificamos as principais altera\u00e7\u00f5es necess\u00e1rias para a portabilidade bem-sucedida para a vers\u00e3o 3. Alguns dos problemas sobre os quais voc\u00ea ler\u00e1 foram identificados durante o processo de portabilidade. Nosso objetivo ao compartilhar nossos aprendizados \u00e9 ajud\u00e1-lo em sua pr\u00f3pria migra\u00e7\u00e3o. Voc\u00ea pode escolher a vers\u00e3o mais recente do Python 3.x (depende da vers\u00e3o de pr\u00e9-lan\u00e7amento, est\u00e1vel e com corre\u00e7\u00f5es de seguran\u00e7a em uma plataforma espec\u00edfica, 3.7 ou 3.6), \u00e0 qual nos referimos como Python 3 em todo este blog. Veja mais detalhes sobre o lan\u00e7amento em <\/span><a href=\"https:\/\/www.python.org\/downloads\/\"><span style=\"font-weight: 400\">Download de vers\u00f5es do Python<\/span><\/a><span style=\"font-weight: 400\"> e\u00a0 <\/span><span style=\"font-weight: 400\"><a href=\"https:\/\/docs.python.org\/3\">Documenta\u00e7\u00e3o do Python 3<\/a>.<\/span><\/p>\n<p>Folha de dicas<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Principais altera\u00e7\u00f5es: Python 2 vs. Python 3<\/span><\/h2>\n<p>Para ter uma ideia das principais diferen\u00e7as entre o Python 2 e o Python 3, aqui est\u00e1 a lista resumida das altera\u00e7\u00f5es de c\u00f3digo necess\u00e1rias.<\/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\">O texto \u00e9 unicode : str<\/span><br \/>\n<span style=\"font-weight: 400\">u\"<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Bin\u00e1rio \u00e9 o mesmo que Texto: bytes\/str<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo:<\/span><br \/>\n<span style=\"font-weight: 400\">file.read(6) == 'GIF89a'<\/span><\/td>\n<td><span style=\"font-weight: 400\">Os dados bin\u00e1rios s\u00e3o representados como prefixo b: bytes<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0b\"<\/span><br \/>\n<span style=\"font-weight: 400\">Use decode() para obter a string, encode() para obter bytes.<\/span><span style=\"font-weight: 400\">Exemplos:\u00a0<\/span><br \/>\n<span style=\"font-weight: 400\">file.read(6) == b'GIF89a'<\/span><br \/>\n<span style=\"font-weight: 400\">b'hello'.decode() \u2192 'hello'<\/span><br \/>\n<span style=\"font-weight: 400\">'hello'.encode() \u2192 b'hello'<\/span><br \/>\n<span style=\"font-weight: 400\"><span style=\"font-weight: 400\">str(b'hello') \u2192 \"b'hello'<\/span><\/span>&#8220;<\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Imprimir declara\u00e7\u00e3o<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: print ' '<\/span><\/td>\n<td><span style=\"font-weight: 400\">Fun\u00e7\u00e3o de impress\u00e3o<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: print(' ')<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Divis\u00e3o de n\u00fameros inteiros<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: 5\/2=2<\/span><\/td>\n<td><span style=\"font-weight: 400\">Divis\u00e3o de andares. Use 2 barras<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: 5\/\/2 = 2 e 5\/2=2,5<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Divis\u00e3o de flutua\u00e7\u00e3o<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: 5\/2,0 = 2,5 ou 5,0\/2 = 2,5<\/span><\/td>\n<td><span style=\"font-weight: 400\">Divis\u00e3o de flutua\u00e7\u00e3o. Use uma barra simples<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: 5\/2 = 2.5<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">O tipo long \u00e9 diferente de int<\/span><br \/>\n<span style=\"font-weight: 400\">longo\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">N\u00e3o existe um tipo long. Ele \u00e9 igual a int<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">xrange()<\/span><\/td>\n<td><span style=\"font-weight: 400\">intervalo()<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">As fun\u00e7\u00f5es de itera\u00e7\u00e3o tinham o prefixo iter. iterxxx()<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: iteritems()<\/span><\/td>\n<td><span style=\"font-weight: 400\">O prefixo do iter foi removido. xxxx()<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: items()<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">As listas s\u00e3o carregadas diretamente (todos os elementos s\u00e3o carregados na mem\u00f3ria quando a lista \u00e9 usada)<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: for i in []\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">As listas s\u00e3o carregadas de forma pregui\u00e7osa (quando um elemento \u00e9 acessado, ele s\u00f3 \u00e9 carregado na mem\u00f3ria)<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: for i in list([])\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Os dicion\u00e1rios podem ser comparados por padr\u00e3o ou com 2 dicion\u00e1rios.<\/span><br \/>\n<span style=\"font-weight: 400\">Exemplo: sorted(dict)\u00a0<\/span><\/td>\n<td><span style=\"font-weight: 400\">Os dicion\u00e1rios n\u00e3o podem ser comparados diretamente. sorted() deve ter uma chave.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Exemplo: <\/span><span style=\"font-weight: 400\">sorted(expected_result,key=(lambda x: x[bucket.name]['name']))<\/span><span style=\"font-weight: 400\">Para compara\u00e7\u00e3o geral de ditado\/lista, voc\u00ea pode usar o seguinte:\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_real['resultados'], resultado_esperado[<\/span><b>'resultados'<\/b><span style=\"font-weight: 400\">], <\/span><span style=\"font-weight: 400\">ignore_order<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadeiro<\/b><span style=\"font-weight: 400\">)<\/span><b>se <\/b><span style=\"font-weight: 400\">diffs:<\/span><br \/>\n<span style=\"font-weight: 400\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400\">aut\u00f4nomo<\/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 e cadeias de caracteres como valores:<\/span><br \/>\n<span style=\"font-weight: 400\">diffs = DeepDiff(<\/span><span style=\"font-weight: 400\">definir<\/span><span style=\"font-weight: 400\">(actual_indexes), <\/span><span style=\"font-weight: 400\">definir<\/span><span style=\"font-weight: 400\">(indexes_names), <\/span><span style=\"font-weight: 400\">ignore_order<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadeiro<\/b><span style=\"font-weight: 400\">, <\/span><span style=\"font-weight: 400\">ignore_string_type_changes<\/span><span style=\"font-weight: 400\">=<\/span><b>Verdadeiro<\/b><span style=\"font-weight: 400\">)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">string.replace(data[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\">Novos m\u00f3dulos<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">http.client<\/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\">Exemplos:\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\">string.lowercase<\/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\">Veja o <\/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 mudan\u00e7as<\/span><\/p>\n<h2><\/h2>\n<h2><span style=\"font-weight: 400\">Configura\u00e7\u00e3o do Python 3<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Para configurar o Python 3 do zero, execute os comandos abaixo em um novo host com as principais plataformas suportadas.<\/span><br \/>\n<span style=\"font-weight: 400\">Posteriormente, durante o tempo de execu\u00e7\u00e3o, use o comando python 3 ou python no ambiente virtual do python 3. Use pip3 ou pip3.x (pip3.6, por exemplo) para instalar pacotes com base na vers\u00e3o do Python 3 instalada.<\/span><\/p>\n<div class=\"responsive-table\">\n<table>\n<tbody>\n<tr>\n<td><b>Mac OS<\/b><br \/>\n(Exemplo: seu laptop)<br \/>\n<span style=\"font-weight: 400\">Configura\u00e7\u00e3o direta (pip3 instalado automaticamente):<\/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\">Configura\u00e7\u00e3o do ambiente 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 as bibliotecas necess\u00e1rias:<\/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 enquanto, a modifica\u00e7\u00e3o abaixo \u00e9 necess\u00e1ria para o cliente http comum do Python 3; caso contr\u00e1rio, voc\u00ea receber\u00e1 um erro.<\/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\">Exemplo de n\u00f3: Jenkins Slave)<\/span><br \/>\nConfigura\u00e7\u00e3o direta e ambiente 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 as bibliotecas necess\u00e1rias:<\/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\">Realizar a instala\u00e7\u00e3o do Couchbase CSDK e do Python SDK no novo slave:<\/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 enquanto, a modifica\u00e7\u00e3o abaixo \u00e9 necess\u00e1ria para o cliente http comum do Python 3; caso contr\u00e1rio, voc\u00ea receber\u00e1 um erro.<\/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>Ubuntu slave usando para verifica\u00e7\u00e3o do tempo de execu\u00e7\u00e3o do Python 3<\/b><br \/>\nConfigura\u00e7\u00e3o direta:<\/p>\n<pre class=\"lang:sh decode:true\"># apt install python3-pip<\/pre>\n<p>&nbsp;<\/p>\n<p>Instale as bibliotecas necess\u00e1rias:<\/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\">Instala\u00e7\u00e3o do CSDK e do 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 enquanto, a modifica\u00e7\u00e3o abaixo \u00e9 necess\u00e1ria para o cliente http comum do Python 3; caso contr\u00e1rio, voc\u00ea receber\u00e1 um erro.<\/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\">Fa\u00e7a o download e instale: <\/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 as bibliotecas necess\u00e1rias:<\/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\">Processo de portabilidade<\/span><\/h2>\n<p>Em um n\u00edvel elevado, a portabilidade \u00e9 um processo de tr\u00eas etapas. 1) Convers\u00e3o autom\u00e1tica 2) Altera\u00e7\u00f5es manuais 3) Valida\u00e7\u00e3o e corre\u00e7\u00e3o em tempo de execu\u00e7\u00e3o<\/p>\n<p>Em um primeiro momento, clone o reposit\u00f3rio original e fa\u00e7a as altera\u00e7\u00f5es b\u00e1sicas de convers\u00e3o autom\u00e1tica. Fa\u00e7a o check-in das altera\u00e7\u00f5es como um novo reposit\u00f3rio at\u00e9 que a convers\u00e3o completa seja conclu\u00edda. Dessa forma, os ciclos de regress\u00e3o atuais podem continuar sem interrup\u00e7\u00e3o.<\/p>\n<h3><span style=\"font-weight: 400\">1. Convers\u00e3o autom\u00e1tica<\/span><\/h3>\n<p><span style=\"font-weight: 400\">H\u00e1 uma ferramenta automatizada chamada <\/span><a href=\"https:\/\/docs.python.org\/2\/library\/2to3.html#\"><span style=\"font-weight: 400\">2para3<\/span><\/a> ferramenta<span style=\"font-weight: 400\">fornecida pela equipe do Python 3, que ajuda a cuidar de alguns padr\u00f5es comuns, como impress\u00e3o, exce\u00e7\u00e3o, encapsulamento de lista, importa\u00e7\u00f5es relativas etc.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Voc\u00ea pode come\u00e7ar com um \u00fanico diret\u00f3rio no espa\u00e7o de trabalho clonado localmente para fazer uma verifica\u00e7\u00e3o dupla. Posteriormente, a convers\u00e3o pode ser feita inteiramente em todo o c\u00f3digo para que a portabilidade b\u00e1sica seja resolvida.<\/span><\/p>\n<p>Abaixo est\u00e3o alguns exemplos de comandos de convers\u00e3o de 2 para 3 no MacOS. No \u00faltimo comando, observe que todas as express\u00f5es idiom\u00e1ticas foram aplicadas. Dessa forma, a primeira convers\u00e3o pode cuidar das altera\u00e7\u00f5es de chave.<\/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. Altera\u00e7\u00f5es manuais<\/span><\/h3>\n<p><span style=\"font-weight: 400\">A convers\u00e3o autom\u00e1tica n\u00e3o faz a portabilidade completa. Os problemas comuns abaixo podem ocorrer durante o processo de portabilidade, al\u00e9m das altera\u00e7\u00f5es comuns de sintaxe feitas pela ferramenta de convers\u00e3o autom\u00e1tica 2to3.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Execute a classe de teste e veja se h\u00e1 algum erro e corrija-o adequadamente, decidindo se deve mudar de bytes para str ou de str para bytes ou algum tipo de problema de compara\u00e7\u00e3o em que seja necess\u00e1rio corrigir o nome da chave na fun\u00e7\u00e3o de classifica\u00e7\u00e3o. Esse \u00e9 um processo iterativo at\u00e9 que todo o tempo de execu\u00e7\u00e3o do c\u00f3digo tenha sido validado.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Quando um padr\u00e3o comum estiver claro, voc\u00ea poder\u00e1 usar o grep e o sed para substituir em v\u00e1rios arquivos de classe. Se voc\u00ea n\u00e3o tiver certeza sobre outro c\u00f3digo at\u00e9 o tempo de execu\u00e7\u00e3o, adie at\u00e9 que a classe de teste seja executada.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Pode haver problemas com bibliotecas\/m\u00f3dulos de terceiros que podem ter sido alterados, que precisam ser pesquisados na Web e usados adequadamente.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Certifique-se de que todo o caminho do c\u00f3digo seja coberto pela execu\u00e7\u00e3o em todas as plataformas e par\u00e2metros suportados.<\/span><\/p>\n<h3>3. Valida\u00e7\u00e3o e corre\u00e7\u00e3o em tempo de execu\u00e7\u00e3o<\/h3>\n<p><span style=\"font-weight: 400\">Depois que a convers\u00e3o for feita, execute muito tempo de execu\u00e7\u00e3o do c\u00f3digo, pois o Python \u00e9 uma linguagem din\u00e2mica. Caso contr\u00e1rio, as altera\u00e7\u00f5es podem quebrar as coisas se voc\u00ea fizer apenas inspe\u00e7\u00e3o\/altera\u00e7\u00f5es visuais de c\u00f3digo est\u00e1tico. Voc\u00ea pode come\u00e7ar com testes b\u00e1sicos de sanidade, testes de aceita\u00e7\u00e3o e, em seguida, selecionar testes completos de um \u00fanico m\u00f3dulo de testes. <\/span><\/p>\n<p><span style=\"font-weight: 400\">Quando estiver confort\u00e1vel, passe a usar todos os outros m\u00f3dulos, um a um. Continue verificando as altera\u00e7\u00f5es no novo reposit\u00f3rio. Al\u00e9m disso, voc\u00ea precisa ter certeza de que n\u00e3o h\u00e1 regress\u00f5es com as altera\u00e7\u00f5es portadas desse novo reposit\u00f3rio, executando testes de sanidade nas compila\u00e7\u00f5es mais recentes. Al\u00e9m disso, a valida\u00e7\u00e3o deve incluir todas as plataformas compat\u00edveis com o Python 3.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">C\u00f3digo portado e status do Python 3<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Veja abaixo onde encontrar o novo reposit\u00f3rio para o c\u00f3digo portado do Python 3 at\u00e9 que ele seja mesclado ao reposit\u00f3rio principal. O plano \u00e9 fazer um ciclo de portabilidade ou, de forma intermedi\u00e1ria, pegar as altera\u00e7\u00f5es do reposit\u00f3rio principal e fazer uma mesclagem manual com esse reposit\u00f3rio.<\/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\">(Branch: master)<\/span><\/p>\n<p><span style=\"font-weight: 400\">Muitas altera\u00e7\u00f5es comuns j\u00e1 foram feitas, mas n\u00e3o foram conclu\u00eddas, pois pode haver outros problemas de tempo de execu\u00e7\u00e3o. As corre\u00e7\u00f5es em comum tamb\u00e9m podem ser revertidas para as corre\u00e7\u00f5es anteriores devido a suposi\u00e7\u00f5es sobre convers\u00f5es de tipo de valor de entrada. Ainda h\u00e1 mais alguns c\u00f3digos portados a serem validados com o Python 3 e o esfor\u00e7o ainda est\u00e1 em andamento.<\/span><\/p>\n<p>Agora, vou lhe mostrar os problemas comuns <span style=\"font-weight: 400\">que ocorreu<\/span> durante a valida\u00e7\u00e3o do tempo de execu\u00e7\u00e3o. Voc\u00ea pode usar isso como refer\u00eancia quando tiver um problema para ver se est\u00e1 tendo um problema semelhante. Voc\u00ea pode aplicar a mesma solu\u00e7\u00e3o e ver se ela funciona para voc\u00ea. <span style=\"font-weight: 400\">E se voc\u00ea tiver algum<\/span> novas ideias, voc\u00ea pode coloc\u00e1-las nos coment\u00e1rios.<\/p>\n<h2><span style=\"font-weight: 400\">Problemas comuns de tempo de execu\u00e7\u00e3o<\/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\">Voc\u00ea pode receber alguns dos TypeErrors abaixo durante o tempo de execu\u00e7\u00e3o, como str em vez de bytes e bytes em vez de str<\/span><\/li>\n<li><span style=\"font-weight: 400\">Error#1. TypeError: n\u00e3o \u00e9 poss\u00edvel concatenar str com bytes<\/span><\/li>\n<li><span style=\"font-weight: 400\">Error#2. TypeError: deve ser str, n\u00e3o 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: \u00e9 necess\u00e1rio um objeto do tipo bytes, n\u00e3o '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: N\u00e3o \u00e9 poss\u00edvel misturar argumentos str e n\u00e3o 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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Veja os tipos das vari\u00e1veis na declara\u00e7\u00e3o e use xxx.encode() para obter os bytes ou xxx.decode() para obter a string ou use o prefixo b ou use str(). \u00c0s vezes, a entrada pode n\u00e3o ser desconhecida e, nesse 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 - ERRO - ---&gt;instala\u00e7\u00e3o falhou: \u00e9 necess\u00e1rio um objeto do tipo bytes, n\u00e3o 'str'<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Solu\u00e7\u00e3o(\u00f5es):\u00a0 <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Nesse caso, adicione b como prefixo \u00e0 string em compara\u00e7\u00e3o ou altere o tipo de byte para o tipo de string. Exemplo: 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\">Envolva o try-except para verificar a linha exata que est\u00e1 causando o erro (digamos, acima do 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\">Exemplo de sa\u00edda ap\u00f3s traceback.print_exec() para ver o rastreamento completo da pilha de forma semelhante ao java.<\/span><\/p>\n<p>Corrigir com altera\u00e7\u00f5es no lib\/remote\/remote_util.py conforme abaixo.<\/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\">Solu\u00e7\u00e3o(\u00f5es): <\/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 suite_setUp() ou suite_tearDown() est\u00e3o faltando em alguns conjuntos de teste.<\/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\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Adicione os m\u00e9todos dummy suite_setUp() e 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\">Solu\u00e7\u00e3o(\u00f5es):<\/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: o objeto 'Transport' n\u00e3o tem o atributo '_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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">N\u00e3o h\u00e1 parada direta de um thread n\u00e3o-dem\u00f4nico. Mas, em termos de sintaxe, use t._stop(). A recomenda\u00e7\u00e3o \u00e9 usar o desligamento gracioso usando um sinalizador global e verificar na execu\u00e7\u00e3o() do thread para interromper.<\/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\">O teste expirytests.ExpiryTests.test_expired_keys n\u00e3o foi encontrado: o m\u00f3dulo 'string' n\u00e3o tem o atributo 'translate'<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Reescreva com m\u00e9todos est\u00e1ticos str. N\u00e3o existe uma maneira antiga de obter todos os caracteres, portanto, usamos o c\u00f3digo anterior e o conjunto total.<\/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 inconsistente de tabula\u00e7\u00f5es e espa\u00e7os na indenta\u00e7\u00e3o<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Procure caracteres de tabula\u00e7\u00e3o e substitua por caracteres de espa\u00e7o.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Para o problema acima, remova os caracteres de tabula\u00e7\u00e3o.<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Problema de sensibilidade a mai\u00fasculas e min\u00fasculas. Corrigido com a altera\u00e7\u00e3o da chave x_couchbase_meta para 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; n\u00e3o \u00e9 suportado entre inst\u00e2ncias de &#039;dict&#039; e &#039;dict&#039;<\/span><\/li>\n<li><span style=\"font-weight: 400\">Erro#2. TypeError: 'cmp' \u00e9 um argumento de palavra-chave inv\u00e1lido para esta fun\u00e7\u00e3o<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/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\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Aqui, ele deve retornar int, pois o python 3 n\u00e3o compara automaticamente como no 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\">Solu\u00e7\u00e3o(\u00f5es):<\/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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Converteu a chave em string para que ch seja string em vez de int com chave bin\u00e1ria. Veja o arquivo.<\/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: o objeto 'FileNotFoundError' n\u00e3o \u00e9 subescritur\u00e1vel<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Alterado no Python 3, pois FileNotFoundError n\u00e3o \u00e9 subescritur\u00e1vel e, em vez disso, use o 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\">Solu\u00e7\u00e3o(\u00f5es):<\/span><\/h4>\n<p><span style=\"font-weight: 400\">A compara\u00e7\u00e3o de dicion\u00e1rio\/lista aninhada n\u00e3o estava funcionando porque a fun\u00e7\u00e3o de classifica\u00e7\u00e3o anterior para classificar completamente agora n\u00e3o est\u00e1 dispon\u00edvel. Use o m\u00f3dulo deepdiff e a classe DeepDiff para fazer a compara\u00e7\u00e3o<\/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: o m\u00f3dulo 'string' n\u00e3o tem o atributo '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\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Use a vari\u00e1vel direct str para substituir como mostrado abaixo para corrigir o 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\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Use a fun\u00e7\u00e3o str ou int adequadamente.<\/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: o nome 'cmp' n\u00e3o est\u00e1 definido<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Solu\u00e7\u00e3o(\u00f5es): <\/span><\/h4>\n<p><span style=\"font-weight: 400\">Use o m\u00f3dulo deepdiff e a classe DeepDiff para fazer a compara\u00e7\u00e3o de 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\">Solu\u00e7\u00e3o(\u00f5es): <\/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\">Converta str em int como abaixo para o problema de erro de tipo acima.<\/span><\/p>\n<pre class=\"lang:python decode:true\">return int(self.itr) &lt; int(self.end)<\/pre>\n<p>&#8212;-<\/p>\n<p>Por enquanto, isso \u00e9 tudo na lista de problemas a serem observados quando voc\u00ea atualizar o Python vers\u00e3o 2 para o Python vers\u00e3o 3. Publicaremos mais aprendizados em futuras postagens no blog. Enquanto isso, boa sorte na migra\u00e7\u00e3o!<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Leituras adicionais<\/span><\/h2>\n<p>As refer\u00eancias a seguir nos ajudaram. Voc\u00ea tamb\u00e9m pode ler mais nos links de refer\u00eancia abaixo para obter mais detalhes e melhorar a portabilidade do seu c\u00f3digo para o 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 voc\u00ea tenha se divertido com a leitura!<\/p>\n<p><strong>Isen\u00e7\u00e3o de responsabilidade:<\/strong> Por favor, veja isso como uma refer\u00eancia r\u00e1pida para a atualiza\u00e7\u00e3o do Python 3, em vez de um guia completo para resolver problemas de portabilidade. Nossa inten\u00e7\u00e3o aqui \u00e9 ajud\u00e1-lo em algum n\u00edvel e dar um empurr\u00e3ozinho no processo de portabilidade. Sinta-se \u00e0 vontade para compartilhar se tiver aprendido algo novo que possa nos ajudar. Seu feedback positivo \u00e9 muito bem-vindo!<\/p>\n<p>&nbsp;<\/p>\n<p>&#8212;<\/p>\n<p>Agradecemos a Raju Suravarjjala e Keshav Murthy por suas principais contribui\u00e7\u00f5es e feedback.<\/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 v26.2 (Yoast SEO v26.2) - 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\/pt\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\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\/pt\/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\":\"pt-BR\",\"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\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@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\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@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\":\"pt-BR\",\"@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\/pt\/author\/jagadesh\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Python 2 to 3 Migration: How to Update & Key Differences","description":"Saiba como atualizar do Python 2 para o 3 nesta postagem do Couchbase. Tamb\u00e9m abordamos suas principais diferen\u00e7as e identificamos problemas comuns com a migra\u00e7\u00e3o.","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\/pt\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/","og_locale":"pt_BR","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\/pt\/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":"pt-BR","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":"Saiba como atualizar do Python 2 para o 3 nesta postagem do Couchbase. Tamb\u00e9m abordamos suas principais diferen\u00e7as e identificamos problemas comuns com a migra\u00e7\u00e3o.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/tips-and-tricks-for-upgrading-from-python-2-to-python-3\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@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":"Blog do Couchbase","description":"Couchbase, o banco de dados 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":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@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, engenheiro de software principal, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@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 \u00e9 engenheiro de software principal da Couchbase Inc., EUA. EUA. Antes disso, ele foi veterano na Sun Microsystems e na Oracle por 19 anos. Jagadesh \u00e9 mestre em engenharia de software pela San Jose State University, EUA, e bacharel em tecnologia. Ci\u00eancia e Engenharia da Computa\u00e7\u00e3o na JNTU, \u00cdndia. Ele \u00e9 autor do \"Software Quality and Java Automation Engineer Survival Guide\" para ajudar desenvolvedores de software e engenheiros de automa\u00e7\u00e3o de qualidade.","url":"https:\/\/www.couchbase.com\/blog\/pt\/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","author_category":"","last_name":"Munta, Principal Software Engineer, Couchbase","first_name":"Jagadesh","job_title":"","user_url":"","description":"Jagadesh Munta \u00e9 engenheiro de software principal da Couchbase Inc., EUA. EUA. Antes disso, ele foi veterano na Sun Microsystems e na Oracle por 19 anos. Jagadesh \u00e9 mestre em engenharia de software pela San Jose State University, EUA, e bacharel em tecnologia. Ci\u00eancia e Engenharia da Computa\u00e7\u00e3o na JNTU, \u00cdndia. Ele \u00e9 autor do \"Software Quality and Java Automation Engineer Survival Guide\" para ajudar desenvolvedores de software e engenheiros de automa\u00e7\u00e3o de qualidade."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/7726","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/46261"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=7726"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/7726\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/9922"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=7726"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=7726"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=7726"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=7726"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}