{
  "path": "/debugando-um-problema-de-recursao-no-python.html",
  "site": "at://did:plc:3272gdrjsuikiff7qsgokgas/site.standard.publication/3mjaxtes2yf2v",
  "tags": [
    "pt",
    "Python",
    "Dev"
  ],
  "$type": "site.standard.document",
  "title": "Debugando um problema de recursão no Python",
  "publishedAt": "2020-07-06T00:00:00.000Z",
  "textContent": "Em um fórum que participo apareceu uma dúvida e a forma como a interação fluiu para encontrarmos a solução foi bem interessante. Então compartilho um resumo neste blog, assim, talvez ajudamos mais gente ainda!\n\nA ideia aqui é falar sobre perder o medo de ler as mensagens de erro e usá-las como guia para resolver problemas, para encontrar o que está dando problema e então, ser precisa em saber o que precisa ser solucionado. Primeiro, ajudei a pessoa a ler o a mensagem de erro e relacioná-la ao código que a pessoa havia escrito. Depois, entendemos a mensagem de erro e, por fim, propusemos uma solução.\n\nMas começemos pelo princípio! A mensagem incial dizia:\n\n> Estou tentando fazer uma simulação bem básica do mecanismo de prova de trabalho da _blockchain_:\n>\n> \n>\n> E estou tendo um erro:\n>\n> \n\nEncontrando o problema\n\nA primeira coisa que notei é que a falta do _traceback_ completo não ajudava a gente a ajudar a pessoa que tinha dúvida.\n\nO _traceback_ é o histórico do erro, da chamada do código que a gente escreveu, passando por toda estrutura da aplicação, biblioteca de terceiros ou código fonte do Python, até chegar na linha que gera o erro. Como diz o Henrique Bastos:\n\n> Quando um comando dá errado ou o resultado não é o esperado, é muito importante publicar a entrada e a saída na íntegra.\n> \n> _Printar_ a tela geralmente oculta informações importantes. Por isso é importante que você selecione no terminal, copie e cole as linhas na íntegra desde o comando até o final da mensagem de erro.\n\nPedi então ao amigo que estava com a dúvida, o _traceback_ todo e a coisa ficou melhor:\n\n> \n\nLendo esse trecho ficou claro o _trajeto_ na execução do código, começando pela linha 37 — generate('t1, t2, t3, t4', '00'):\n\nEssa chamada da função generate leva a execução ao ponto onde a função generate é definida, e a execução prossegue dali até a linha 14 — generate_with_nonce(data, dificult, 0), com uma chamada de outra função:\n\nE assim por diante até a última linha do código executada que a pessoa havia escrito, a linha 10:\n\nEm outras palavras, agora eu sabia precisamenete qual parte do código causava o erro:\n\nO problema aí foi que essa linha fazia muita coisa:\n\n1. Tem uma conversão para string em str(nonce)\n1. Tem um concatenação de string com data +\n1. Tem uma conversão para bytes com o .encode(…)\n1. Tem a criação de um _hash_ com o sha256(…)\n1. Tem um cálculo de hexadecimal com .hexdigest()\n\nAlguns desses passos podem ter ainda conversões de objetos para _string_ por debaixo dos panos. Então fica difícil saber o que exatamente está causando o erro. Eu sugeri tentar isolar esses passos para identificar qual passo dá problema, e aí sim pensar em uma solução mais precisa. Sugeri esse _refactor_ para essa linha:\n\nBingo. Executando com essa nova versão e usando a mesma estratégia, descobrimos que o RecursionError estava exatamente em nonce = str(nonce). Excelente!\n\nEntendendo o erro\n\nComo a pessoa bem resumiu, o RecursionError é o que acontece no Python quando uma função recursivamente chama outra várias vezes – milhares de vezes, fazendo o computador achar que está em um _loop_ infinito. Por segurança, então, ele pára esse ciclo com esse tipo de erro.\n\nAnalisando o código vi que a cada chamada da generate_with_nonce, o valor de data era passado para mod_hash — e generate_with_nonce é uma função recursiva, ou seja, ela _se chama_ diversas vezes. No entanto reparei também que o valor de data não mudava a cada chamada recursiva, era sempre o mesmo que a primeira chamada, a que desencadeia a exexecução recursiva. Em outras palavras, poderíamos executar o nonce = str(nonce) apenas uma vez, na primeira execução da generate_with_nonce, e apenas se nonce ainda não fosse _bytes_.\n\nSolução proposta\n\nCom base nessa análise, sugeri o seguinte _refactor_:\n\nAssim, problema resolvido, com um pouco de reflexão lendo o fluxo de execução, o famoso _traceback_ : )",
  "canonicalUrl": "https://cuducos.me/debugando-um-problema-de-recursao-no-python.html"
}