Introdução
A última grande atualização do Python - para a versão 3 - ocorreu em dezembro de 2008, há quase 12 anos. No entanto, há uma boa chance de que você ainda esteja trabalhando no produto Python 2 ou no código de teste. Nesse caso, você pode estar vendo a mensagem de depreciação abaixo como um lembrete para atualizar a versão do Python com a qual está trabalhando.
"DEPRECATION: O Python 2.7 chegará ao fim de sua vida útil em 1º de janeiro de 2020. Atualize seu Python, pois o Python 2.7 não será mantido após essa data. Uma versão futura do pip deixará de oferecer suporte ao Python 2.7."
Leve isso a sério e planeje adequadamente: As atualizações do Python para a versão 3.x não são compatíveis com versões anteriores. O que você escreve com as versões 2.x do Python pode não funcionar corretamente quando usar a 3.x.
Não deixe de ler também as letras miúdas. De acordo com o site da linguagem de programação, a data final de lançamento da atualização do Python ainda é uma incógnita: "Por ser a última da série 2.x, a versão 2.7 receberá suporte para correção de bugs até 2020. O suporte será oficialmente interrompido em 1º de janeiro de 2020, mas a versão final ocorrerá após essa data." [1]
Portanto, o Python 2 entrará no modo sem suporte até o final deste ano. Se você ainda não tiver feito isso, agora é um bom momento para migrar o código atual do Python 2 para a sintaxe do Python 3 e manter o Python 3 daqui para frente.
Por que as equipes simplesmente não iniciam essa migração do Python 2 para o 3? Um dos principais obstáculos é que a maioria dos códigos funcionais simplesmente quebra (leia mais em why-was-python-3-made-incompatible-with-python-2), seja por causa da sintaxe direta da linguagem ou por problemas com APIs de terceiros. Sejamos justos: poucos de nós se preocupariam com a migração se as novas atualizações do Python fossem compatíveis com as versões anteriores. Em vez disso, a versão 2 ficará sem suporte, forçando muitos - inclusive nós aqui no Couchbase - a priorizar a migração. Mesmo que a equipe ultrapasse o prazo de suporte para correção de bugs, não há problema (porque seu código ainda está funcionando). Como equipe, decidimos que é melhor migrar o mais próximo possível dessa data para que possamos estar na mesma página que outros membros da comunidade Python e aprender com eles.
Este documento é uma coleção de dicas e truques que aprendemos durante a atualização para o Python 3, juntamente com problemas comuns que encontramos durante o processo de migração da infraestrutura de teste do Couchbase. Como você verá, 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ção do python da versão 2 para a versão 3 é importante.
Couchbase é um banco de dados NoSQL de classe empresarial de código aberto, do MultiCloud ao Edge. A estrutura de teste funcional do Couchbase, TestRunner, foi desenvolvida em Python 2. O repositório git do TestRunner pode ser encontrado em https://github.com/couchbase/testrunner . Nosso objetivo agora é mudar completamente para o tempo de execução do Python 3 em vez de executar conjuntamente o Python 3 e o Python 2.
Como parte do processo de atualização do Python, identificamos as principais alterações necessárias para a portabilidade bem-sucedida para a versão 3. Alguns dos problemas sobre os quais você lerá foram identificados durante o processo de portabilidade. Nosso objetivo ao compartilhar nossos aprendizados é ajudá-lo em sua própria migração. Você pode escolher a versão mais recente do Python 3.x (depende da versão de pré-lançamento, estável e com correções de segurança em uma plataforma específica, 3.7 ou 3.6), à qual nos referimos como Python 3 em todo este blog. Veja mais detalhes sobre o lançamento em Download de versões do Python e Documentação do Python 3.
Folha de dicas
Principais alterações: Python 2 vs. Python 3
Para ter uma ideia das principais diferenças entre o Python 2 e o Python 3, aqui está a lista resumida das alterações de código necessárias.
Python 2 | Python 3 |
Texto utf-8 : str ‘‘ |
O texto é unicode : str u" |
Binário é o mesmo que Texto: bytes/str Exemplo: file.read(6) == 'GIF89a' |
Os dados binários são representados como prefixo b: bytes b" Use decode() para obter a string, encode() para obter bytes.Exemplos: file.read(6) == b'GIF89a' b'hello'.decode() → 'hello' 'hello'.encode() → b'hello' str(b'hello') → "b'hello'“ |
Imprimir declaração Exemplo: print ' ' |
Função de impressão Exemplo: print(' ') |
Divisão de números inteiros Exemplo: 5/2=2 |
Divisão de andares. Use 2 barras Exemplo: 5//2 = 2 e 5/2=2,5 |
Divisão de flutuação Exemplo: 5/2,0 = 2,5 ou 5,0/2 = 2,5 |
Divisão de flutuação. Use uma barra simples Exemplo: 5/2 = 2.5 |
O tipo long é diferente de int longo |
Não existe um tipo long. Ele é igual a int |
xrange() | intervalo() |
As funções de iteração tinham o prefixo iter. iterxxx() Exemplo: iteritems() |
O prefixo do iter foi removido. xxxx() Exemplo: items() |
As listas são carregadas diretamente (todos os elementos são carregados na memória quando a lista é usada) Exemplo: for i in [] |
As listas são carregadas de forma preguiçosa (quando um elemento é acessado, ele só é carregado na memória) Exemplo: for i in list([]) |
Os dicionários podem ser comparados por padrão ou com 2 dicionários. Exemplo: sorted(dict) |
Os dicionários não podem ser comparados diretamente. sorted() deve ter uma chave.
Exemplo: sorted(expected_result,key=(lambda x: x[bucket.name]['name']))Para comparação geral de ditado/lista, você pode usar o seguinte: Bytes e cadeias de caracteres como valores: |
string.replace(data[i],...) | data[i].replace(..) |
urllib.urlencode() | Novos módulos
Exemplos: |
string.lowercase | Atributos: string.ascii_lowercase string.ascii_uppercase |
Veja o testrunner py3 commits para mudanças
Configuração do Python 3
Para configurar o Python 3 do zero, execute os comandos abaixo em um novo host com as principais plataformas suportadas.
Posteriormente, durante o tempo de execução, 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ão do Python 3 instalada.
Mac OS (Exemplo: seu laptop) Configuração direta (pip3 instalado automaticamente):(https://wsvincent.com/install-python3-mac/)
Configuração do ambiente virtual:
Instale as bibliotecas necessárias:
Por enquanto, a modificação abaixo é necessária para o cliente http comum do Python 3; caso contrário, você receberá um erro.
|
||||||||
CentOS (Exemplo de nó: Jenkins Slave) Configuração direta e ambiente virtual:
Instale as bibliotecas necessárias:
Realizar a instalação do Couchbase CSDK e do Python SDK no novo slave:
Por enquanto, a modificação abaixo é necessária para o cliente http comum do Python 3; caso contrário, você receberá um erro.
|
||||||||
Ubuntu slave usando para verificação do tempo de execução do Python 3 Configuração direta:
Instale as bibliotecas necessárias:
Instalação do CSDK e do Python SDK: (Ref: https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html )
Por enquanto, a modificação abaixo é necessária para o cliente http comum do Python 3; caso contrário, você receberá um erro.
|
||||||||
Windows Faça o download e instale: https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe
Instale as bibliotecas necessárias:
|
Processo de portabilidade
Em um nível elevado, a portabilidade é um processo de três etapas. 1) Conversão automática 2) Alterações manuais 3) Validação e correção em tempo de execução
Em um primeiro momento, clone o repositório original e faça as alterações básicas de conversão automática. Faça o check-in das alterações como um novo repositório até que a conversão completa seja concluída. Dessa forma, os ciclos de regressão atuais podem continuar sem interrupção.
1. Conversão automática
Há uma ferramenta automatizada chamada 2para3 ferramentafornecida pela equipe do Python 3, que ajuda a cuidar de alguns padrões comuns, como impressão, exceção, encapsulamento de lista, importações relativas etc.
Você pode começar com um único diretório no espaço de trabalho clonado localmente para fazer uma verificação dupla. Posteriormente, a conversão pode ser feita inteiramente em todo o código para que a portabilidade básica seja resolvida.
Abaixo estão alguns exemplos de comandos de conversão de 2 para 3 no MacOS. No último comando, observe que todas as expressões idiomáticas foram aplicadas. Dessa forma, a primeira conversão pode cuidar das alterações de chave.
1 2 3 4 5 6 |
(myenv) jmunta-mac:myscripts jagadeshmunta$ 2para3 . -o novo -n -w . hq-mac:testrunner jagadeshmunta$ cd lib; mv lib/couchbase_ajudante ../ajudante de sofá hq-mac:testrunner jagadeshmunta$ 2para3 -f todos -f buffer -f expressões idiomáticas -f set_literal -f ws_vírgula -n -o ~/p3testrunner_3 -w . |camiseta ~/2to3_3.txt hq-mac:testrunner jagadeshmunta$ tempo 2para3 -f todos -f buffer -f expressões idiomáticas -f set_literal -f ws_vírgula -n -w . |camiseta ~/2to3_4.txt $ 2para3 -f todos -f buffer -f expressões idiomáticas -f set_literal -f ws_vírgula -n -o ~/p3testrunner_helper -w ../ajudante de sofá |camiseta ~/2to3_helper.txt cp -R ~/p3testrunner_helper/* . |
2. Alterações manuais
A conversão automática não faz a portabilidade completa. Os problemas comuns abaixo podem ocorrer durante o processo de portabilidade, além das alterações comuns de sintaxe feitas pela ferramenta de conversão automática 2to3.
Execute a classe de teste e veja se há 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ção em que seja necessário corrigir o nome da chave na função de classificação. Esse é um processo iterativo até que todo o tempo de execução do código tenha sido validado.
Quando um padrão comum estiver claro, você poderá usar o grep e o sed para substituir em vários arquivos de classe. Se você não tiver certeza sobre outro código até o tempo de execução, adie até que a classe de teste seja executada.
Pode haver problemas com bibliotecas/módulos de terceiros que podem ter sido alterados, que precisam ser pesquisados na Web e usados adequadamente.
Certifique-se de que todo o caminho do código seja coberto pela execução em todas as plataformas e parâmetros suportados.
3. Validação e correção em tempo de execução
Depois que a conversão for feita, execute muito tempo de execução do código, pois o Python é uma linguagem dinâmica. Caso contrário, as alterações podem quebrar as coisas se você fizer apenas inspeção/alterações visuais de código estático. Você pode começar com testes básicos de sanidade, testes de aceitação e, em seguida, selecionar testes completos de um único módulo de testes.
Quando estiver confortável, passe a usar todos os outros módulos, um a um. Continue verificando as alterações no novo repositório. Além disso, você precisa ter certeza de que não há regressões com as alterações portadas desse novo repositório, executando testes de sanidade nas compilações mais recentes. Além disso, a validação deve incluir todas as plataformas compatíveis com o Python 3.
Código portado e status do Python 3
Veja abaixo onde encontrar o novo repositório para o código portado do Python 3 até que ele seja mesclado ao repositório principal. O plano é fazer um ciclo de portabilidade ou, de forma intermediária, pegar as alterações do repositório principal e fazer uma mesclagem manual com esse repositório.
https://github.com/couchbaselabs/testrunner-py3/
(Branch: master)
Muitas alterações comuns já foram feitas, mas não foram concluídas, pois pode haver outros problemas de tempo de execução. As correções em comum também podem ser revertidas para as correções anteriores devido a suposições sobre conversões de tipo de valor de entrada. Ainda há mais alguns códigos portados a serem validados com o Python 3 e o esforço ainda está em andamento.
Agora, vou lhe mostrar os problemas comuns que ocorreu durante a validação do tempo de execução. Você pode usar isso como referência quando tiver um problema para ver se está tendo um problema semelhante. Você pode aplicar a mesma solução e ver se ela funciona para você. E se você tiver algum novas ideias, você pode colocá-las nos comentários.
Problemas comuns de tempo de execução
1. Problema(s):
- Você pode receber alguns dos TypeErrors abaixo durante o tempo de execução, como str em vez de bytes e bytes em vez de str
- Error#1. TypeError: não é possível concatenar str com bytes
- Error#2. TypeError: deve ser str, não bytes
-
1234567Arquivo "lib/mc_bin_client.py", linha 53, em __init__ se mensagem: supermsg += ": " + str(mensagem)TypeError: deve ser str, não bytesArquivo "lib/mc_bin_client.py", linha 141, em _recvMsgresposta += dadosTypeError: deve ser str, não bytes
-
- Error#3. TypeError: é necessário um objeto do tipo bytes, não 'str'
-
1234567891011121314151617181920Arquivo "lib/remote/remote_util.py", linha 3038, em log_command_output se "Aviso" em linha e "hugepages" em linha:TypeError: a bytes-como objeto é necessário, não 'str'Arquivo "lib/tasks/task.py", linha 1167, em run_high_throughput_mode aumentar Exceção(rv["err"])Exceção: a bytes-como objeto é necessário, não 'str'Arquivo "lib/mc_bin_client.py", linha 936, em _set_vbucket autônomo.vbucketId = (((zlib.crc32(chave)) >> 16) & 0x7fff) & (autônomo.vbucket_count - 1)TypeError: a bytes-como objeto é necessário, não 'str'Arquivo "lib/mc_bin_client.py", linha 148, em _recvMsgmágica = estrutura.desempacotar(">B", resposta[0:1])[0]TypeError: a bytes-como objeto é necessário, não 'str'Arquivo "lib/remote/remote_util.py", linha 4560, em check_cmd se fora e saída de comando em fora[0]:TypeError: a bytes-como objeto é necessário, não 'str'
-
- Error#4. TypeError: Não é possível misturar argumentos str e não str
-
1234567Arquivo "lib/mc_bin_client.py", linha 126, em _sendMsg autônomo.s.enviar(mensagem + extraHeader + chave + val + dados_meta_extendidos)TypeError: pode't concatenar str para bytesArquivo "/usr/lib64/python3.6/urllib/parse.py", linha 120, em _coerce_argumentosaumentar TypeError("Não é possível misturar argumentos str e não str")TypeError: Não é possível mistura str e não-str argumentos
-
Solução(ões):
Veja os tipos das variáveis na declaração e use xxx.encode() para obter os bytes ou xxx.decode() para obter a string ou use o prefixo b ou use str(). Às vezes, a entrada pode não ser desconhecida e, nesse caso, use try x.encode() except AttributeError: pass
2. Problema(s):
TypeError: root - ERRO - --->instalação falhou: é necessário um objeto do tipo bytes, não 'str'
Solução(ões):
Nesse caso, adicione b como prefixo à string em comparação ou altere o tipo de byte para o tipo de string. Exemplo: lib/remote/remote_util.py
1 2 |
se o[0] != b"": o = o[0].dividir(b" ") |
Envolva o try-except para verificar a linha exata que está causando o erro (digamos, acima do TypeError).
1 2 3 4 5 6 7 8 9 10 11 |
importação rastreamento tentar: .. exceto Exceção como e: registro.informações("{}".formato(e)) rastreamento.print_exc() exc_type, exc_obj, exc_tb = sistema.exc_info() fname = os.path.dividir(exc_tb.tb_frame.f_code.co_filename)[1] impressão(exc_type, fname, exc_tb.tb_lineno) |
Exemplo de saída após traceback.print_exec() para ver o rastreamento completo da pilha de forma semelhante ao java.
Corrigir com alterações no lib/remote/remote_util.py conforme abaixo.
1 2 3 4 5 6 |
3079 para linha em saída: 3080 tentar: 3081 linha=linha.decodificar() 3082 exceto AttributeError: 3083 passe |
3. Problema(s):
1 2 3 |
Arquivo "lib/membase/api/rest_client.py", linha 4178, em multiscan_count_for_gsi_index_with_rest conteúdo = conteúdo.dividir("[]")[0] TypeError: a bytes-como objeto é necessário, não 'str' |
Solução(ões):
1 |
conteúdo = conteúdo.dividir(b'[]')[0].decodificar() |
4. Problema(s):
AttributeError suite_setUp() ou suite_tearDown() estão faltando em alguns conjuntos de teste.
1 |
AttributeError: tipo objeto 'XDCRAdvFilterTests' tem não atributo 'suite_setUp' |
Solução(ões):
Adicione os métodos dummy suite_setUp() e suite_tearDown().
1 2 3 4 5 6 7 8 |
11a12,18 > > def suite_setUp(autônomo): > impressão("*** XDCRAdvFilterTests : suite_Setup() ***") > > def suite_tearDown(autônomo): > impressão("*** XDCRAdvFilterTests : suite_tearDown() ***") > |
5. Problema(s):
1 2 3 |
Arquivo "./testrunner.py", linha 416, em principal resultado.erros = [(nome, e.mensagem)] AttributeError: 'AttributeError' objeto tem não atributo 'mensagem' |
Solução(ões):
1 |
resultado.erros = [(nome, str(e))] |
6. Problema(s):
AttributeError: o objeto 'Transport' não tem o atributo '_Thread__stop'
1 2 3 4 5 6 7 8 9 10 |
Arquivo "./testrunner.py", linha 529, em principal t._Thread__stop() AttributeError: "Transporte objeto tem não atributo '_Thread__stop' Arquivo "pytests/view/viewquerytests.py", linha 45, em parar autônomo._Thread__stop() AttributeError: 'StoppableThread' objeto tem não atributo '_Thread__stop' autônomo._stop() TypeError: 'Evento' objeto é não chamável |
Solução(ões):
Não há parada direta de um thread não-demônico. Mas, em termos de sintaxe, use t._stop(). A recomendação é usar o desligamento gracioso usando um sinalizador global e verificar na execução() do thread para interromper.
(https://stackoverflow.com/questions/27102881/python-threading-self-stop-event-object-is-not-callable)
7. Problema(s):
O teste expirytests.ExpiryTests.test_expired_keys não foi encontrado: o módulo 'string' não tem o atributo 'translate'
Solução(ões):
Reescreva com métodos estáticos str. Não existe uma maneira antiga de obter todos os caracteres, portanto, usamos o código anterior e o conjunto total.
vi lib/membase/api/tap.py
1 2 3 4 5 6 7 8 |
def buildGoodSet(goodChars=string.para impressão, badChar='?'): 143 """Crie uma tabela de tradução que transforme todos os caracteres que não estejam em goodChars 144 para badChar""" 145 todos os caracteres = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123 456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x9 3\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\x bb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\ xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 146 badchars = str.maketrans(todos os caracteres, todos os caracteres, goodChars) 147 badchars1=str.traduzir(todos os caracteres,badchars) 148 rv = str.maketrans(badchars1, badChar * len(badchars1)) 149 retorno rv |
8. Problema(s):
TabError: uso inconsistente de tabulações e espaços na indentação
1 2 3 4 |
Arquivo "pytests/security/audittest.py", linha 396 casca = RemoteMachineShellConnection(autônomo.mestre) ^ TabError: inconsistente uso de guias e espaços em indentação |
Solução(ões):
Procure caracteres de tabulação e substitua por caracteres de espaço.
Para o problema acima, remova os caracteres de tabulação.
1 |
sed -i 's/\t/ /g' testes de pirataria/segurança/teste de auditoria.py |
9. Problema(s):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Arquivo "lib/couchbase_helper/documentgenerator.py", linha 83, em __próximo__ valor = arg[semente % len(arg)] TypeError: lista índices deve ser inteiros ou fatias, não flutuante Arquivo "lib/membase/helper/bucket_helper.py", linha 517, em carregar_algum_dados chaves = ["key_%s_%d" % (testuuid, i) para i em alcance(number_of_buckets)] TypeError: 'float' (flutuante) objeto não pode ser interpretada como e inteiro Arquivo "lib/membase/helper/bucket_helper.py", linha 372, em verificar_dados teste.assertEqual(valor, chave, mensagem='values dont match' (valores não correspondem)) AssertionError: b'key_d918f450-5858-4430-a016-230e1f45bcf9_0' != 'key_d918f450-5858-4430-a016-230e1f45bcf9_0' : valores não partida Arquivo "pytests/setgettests.py", linha 90, em set_get_teste autônomo.teste.falhar("value mismatch for key {0}" (incompatibilidade de valores para a chave {0}).formato(chave)) AssertionError: valor incompatibilidade para chave 9fcbd36f-e34d-477b-9fc5-0a5d067dff4b Arquivo "pytests/security/auditmain.py", linha 320, em returnFieldsDef se (isinstância((detalhes['mandatory_fields'][itens.codificar('utf-8')]), ditado)): KeyError: b'bucket_name' Arquivo "lib/tasks/task.py", linha 2370, em _check_ddoc_revisão new_rev_id = autônomo._parse_revision(meta['rev']) KeyError: 'rev' |
Solução(ões):
Problema de sensibilidade a maiúsculas e minúsculas. Corrigido com a alteração da chave x_couchbase_meta para X_Couchbase_Meta
10. Problema(s):
- Error#1. TypeError: '<' não é suportado entre instâncias de 'dict' e 'dict'
- Erro#2. TypeError: 'cmp' é um argumento de palavra-chave inválido para esta função
1 2 3 |
Arquivo "pytests/tuqquery/tuq_dml.py", linha 455, em test_insert_with_selecionar resultado_esperado = classificado([{balde.nome: {"nome: doc["nome]}} para doc em valores[:num_docs]]) TypeError: '<' não suportado entre instâncias de 'dict' e 'dict' |
Solução(ões):
1 |
resultado_esperado = classificado(resultado_esperado,chave=(lambda x: x[balde.nome]["nome])) |
11. Problema(s):
1 2 3 |
Arquivo "pytests/tuqquery/tuq_2i_index.py", linha 1057, em matriz_teste_simples_índice autônomo.assertTrue(classificado(resultado_real_dentro['resultados']) == classificado(resultado_esperado['resultados'])) TypeError: '<' não suportado entre instâncias de 'dict' e 'dict' |
Solução(ões):
1 2 3 |
- autônomo.assertTrue(classificado(resultado_real_dentro['resultados']) == classificado(resultado_esperado['resultados'])) + autônomo.assertTrue(classificado(resultado_real_dentro['resultados'], chave=(lambda x: x["nome])) == \ + classificado(resultado_esperado['resultados'], chave=(lambda x: x["nome]))) |
12. Problema(s):
1 2 3 4 5 6 7 |
Arquivo "pytests/tuqquery/tuq.py", linha 1221, em _verify_results autônomo.falhar("Os resultados estão incorretos. Número real: %s. Número esperado: %s.\n" % (len(resultado_real), len(resultado_esperado))) AssertionError: Resultados são incorreto.Real num 0. Esperado num: 72. Arquivo "lib/tasks/task.py", linha 3638, em filter_emitted_linhas reverso=descending_set) TypeError: 'cmp' é e inválido palavra-chave argumento para este função |
Solução(ões):
1 |
linhas_esperadas = classificado(autônomo.linhas_emitidas, chave=(lambda x: (x["chave],x['id'])),reverso=descending_set) |
13. Problema(s):
1 2 3 |
Arquivo "lib/tasks/task.py", linha 3675, em <listacomp> linhas_esperadas = [fila para fila em linhas_esperadas se fila["chave] >= chave_inicial e fila["chave] <= end_key] TypeError: '>=' não suportado entre instâncias de 'int' e 'NoneType' |
Solução(ões):
Aqui, ele deve retornar int, pois o python 3 não compara automaticamente como no python 2.
14. Problema(s):
1 |
hasattr(itens,'iteritens') doesn't retorno verdadeiro |
Solução(ões):
1 2 3 4 5 6 7 8 |
@@ -754,7 +755,7 @@ classe Cliente Memcached(objeto): # Se for um dit, converta-o em um gerador de pares coleção = autônomo.nome_da_coleção(coleção) - se hasattr(itens, 'iteritems'): + se hasattr(itens, 'itens'): itens = iter(itens.itens()) se hasattr(itens, 'itens'): |
15. Problema(s):
1 2 3 |
Arquivo "lib/crc32.py", linha 78, em crc32_hash crc = (crc >> 8) ^ crc32tab[int((crc ^ ord(ch)) & 0xff)] TypeError: ord() esperado string de comprimento 1, mas int encontrado |
Solução(ões):
Converteu a chave em string para que ch seja string em vez de int com chave binária. Veja o arquivo.
1 2 3 4 |
tentar: chave = chave.decodificar() exceto AttributeError: passe |
16. Problema(s):
TypeError: o objeto 'FileNotFoundError' não é subescriturável
Solução(ões):
Alterado no Python 3, pois FileNotFoundError não é subescriturável e, em vez disso, use o atributo errno, e.errno
1 2 3 4 5 |
Arquivo "lib/remote/remote_util.py", linha 1714, em criar_diretório se e[0] == 2: TypeError: 'FileNotFoundError' objeto é não subscritível - se e[0] == 2: + se e.errno == 2: |
17. Problema(s):
1 2 3 4 5 6 |
Retrocesso (mais recente chamada último): Arquivo "lib/couchbase_helper/tuq_helper.py", linha 521, em run_query_and_verify_resultado autônomo._verify_results(resultado_real_ordenado, sorted_expected_result) Arquivo "lib/couchbase_helper/tuq_helper.py", linha 114, em _verificar_resultados aumentar Exceção(mensagem) Exceção: O número de linhas partida mas o resultados incompatibilidade, por favor verificar |
Solução(ões):
A comparação de dicionário/lista aninhada não estava funcionando porque a função de classificação anterior para classificar completamente agora não está disponível. Use o módulo deepdiff e a classe DeepDiff para fazer a comparação
18. Problema(s):
AttributeError: o módulo 'string' não tem o atributo 'replace'
1 2 3 |
Arquivo "scripts/populateIni.py", linha 52, em principal dados[i] = string.substituir(dados[i], "dinâmico, servidores[0]) AttributeError: módulo 'string' tem não atributo 'replace' (substituir) |
Solução(ões):
Use a variável direct str para substituir como mostrado abaixo para corrigir o problema.
1 |
dados[i].substituir( "dinâmico, servidores[0]) |
19. Problema(s):
1 |
TypeError: '>' não suportado entre instâncias de 'int' e 'str' |
Solução(ões):
Use a função str ou int adequadamente.
1 2 |
se where_clause: + where_clause = where_clause.substituir('se t > "', 'se str(t) > "') # para corrigir o erro de tipo entre a comparação int, str |
20. Problema(s):
NameError: o nome 'cmp' não está definido
Solução(ões):
Use o módulo deepdiff e a classe DeepDiff para fazer a comparação de objetos.
21. Problema(s):
1 2 3 |
Arquivo "lib/couchbase_helper/tuq_helper.py", linha 782, em verify_indexes_redistribuído se cmp(items_count_before_rebalance, items_count_after_rebalance) != 0: NameError: nome 'cmp' é não definido |
Solução(ões):
1 2 3 4 5 |
Uso deepdiff módulo e DeepDiff classe para fazer objeto comparação. - se cmp(estado do índice antes do rebalanceamento, estado do índice após o rebalanceamento) != 0: + se DeepDiff(estado do índice antes do rebalanceamento, índice_sFile "lib/couchbase_helper/documentgenerator.py", linha 19, em tem_próxima retorno autônomo.itr < autônomo.final TypeError: '<' não suportado entre instâncias de 'int' e 'str' |
Converta str em int como abaixo para o problema de erro de tipo acima.
1 |
retorno int(autônomo.itr) < int(autônomo.final) |
—-
Por enquanto, isso é tudo na lista de problemas a serem observados quando você atualizar o Python versão 2 para o Python versão 3. Publicaremos mais aprendizados em futuras postagens no blog. Enquanto isso, boa sorte na migração!
Leituras adicionais
As referências a seguir nos ajudaram. Você também pode ler mais nos links de referência abaixo para obter mais detalhes e melhorar a portabilidade do seu código para o Python 3.
- https://www.python.org/dev/peps/pep-0373/
- https://wiki.python.org/moin/Python2orPython3
- https://www.toptal.com/python/python-3-is-it-worth-the-switch
- https://weknowinc.com/blog/running-multiple-python-versions-mac-osx
- https://docs.python.org/3/howto/pyporting.html
- https://wsvincent.com/install-python3-mac/
- http://python3porting.com/pdfs/SupportingPython3-screen-1.0-latest.pdf
- https://riptutorial.com/Download/python-language.pdf
- https://docs.couchbase.com/python-sdk/2.5/start-using-sdk.html
- https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html
- https://pypi.org/project/deepdiff/
- https://buildmedia.readthedocs.org/media/pdf/portingguide/latest/portingguide.pdf
- http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf
Espero que você tenha se divertido com a leitura!
Isenção de responsabilidade: Por favor, veja isso como uma referência rápida para a atualização do Python 3, em vez de um guia completo para resolver problemas de portabilidade. Nossa intenção aqui é ajudá-lo em algum nível e dar um empurrãozinho no processo de portabilidade. Sinta-se à vontade para compartilhar se tiver aprendido algo novo que possa nos ajudar. Seu feedback positivo é muito bem-vindo!
—
Agradecemos a Raju Suravarjjala e Keshav Murthy por suas principais contribuições e feedback.