Copiei o seguinte código Ruby da Internet e fiz algumas alterações, mas ele não funciona.
O que posso fazer para depurar o programa sozinho?
Copiei o seguinte código Ruby da Internet e fiz algumas alterações, mas ele não funciona.
O que posso fazer para depurar o programa sozinho?
Respostas:
Instalar via:
$ gem install pry
$ pry
Adicione então:
require 'pry'; binding.pry
no seu programa.
A partir de pry
0.12.2 no entanto, existem comandos nenhuma navegação, como next
, break
, etc. Algumas outras pedras preciosas, adicionalmente, fornecer isso, ver, por exemplo pry-byedebug
.
binding.pry
. Ele também vem com conclusão cor, pesquisa de documentação, e possibilidade de editar dinamicamente e recarregar um método ..
Pry
/ byebug
são ótimos, mas não como seu primeiro passo na depuração. Na maioria dos casos, gerar uma exceção raise object.inspect
resolverá seu problema mais rapidamente do que abrir uma sessão irb. Eu recomendo usar apenas os depuradores de console, uma vez que soluções simples, como gerar uma exceção, não conseguem resolver o seu problema.
pry
? Não consegui descobrir como fazê-lo; e é isso que espero de um depurador.
Em Ruby:
ruby -rdebug myscript.rb
então,
b <line>
: colocar ponto de interrupção n(ext)
ou s(tep)
ec(ontinue)
p(uts)
para exibição(como perl debug)
No Rails: inicie o servidor com
script/server --debugger
e adicione debugger
o código.
-r debug
é lixo?
facets
requisitos da gema e não tive êxito. Para aplicativos antigos do Rails, ruby-debug
é um pouco desagradável, mas faz o trabalho.
Como corrimão recomendado: use alavanca! Só posso concordar com isso.
alavancar é um substituto muito melhor que o irb.
Você precisa adicionar
require 'pry'
ao seu arquivo de origem e insira um ponto de interrupção no seu código-fonte adicionando
binding.pry
no local em que você deseja dar uma olhada nas coisas (isso é como disparar um ponto de interrupção em um ambiente IDE clássico)
Uma vez que seu programa atinge o
binding.pry
Nesta linha, você será jogado diretamente para a réplica, com todo o contexto do seu programa à mão, para que você possa simplesmente explorar tudo ao redor, investigar todos os objetos, alterar estado e até mesmo alterar o código rapidamente.
Eu acredito que você não pode alterar o código do método em que está atualmente, portanto, infelizmente, não pode alterar a próxima linha a ser executada. Mas um bom código ruby tende a ser uma linha única ;-)
Depurar gerando exceções é muito mais fácil do que olhar através deprint
instruções de log e, para a maioria dos bugs, geralmente é muito mais rápido do que abrir um depurador irb comopry
oubyebug
. Essas ferramentas nem sempre devem ser seu primeiro passo.
Exception
então e .inspect
seu resultadoA maneira mais rápida de depurar o código Ruby (especialmente Rails) é raise
uma exceção ao longo do caminho de execução do seu código enquanto chama .inspect
o método ou objeto (por exemplo foo
):
raise foo.inspect
No código acima, raise
dispara um Exception
que interrompe a execução do seu código e retorna uma mensagem de erro que contém convenientemente .inspect
informações sobre o objeto / método (ou seja foo
) na linha que você está tentando depurar.
Essa técnica é útil para examinar rapidamente um objeto ou método ( por exemplo, é nil
? ) E para confirmar imediatamente se uma linha de código está sendo executada em um determinado contexto.
byebug
oupry
Somente depois de obter informações sobre o estado do fluxo de execução de seus códigos, você deve considerar a mudança para um depurador ruby gem irb como pry
ou byebug
onde você pode se aprofundar no estado dos objetos em seu caminho de execução.
Ao tentar depurar um problema, um bom conselho é sempre: Leia a mensagem de erro! @ # $ Ing (RTFM)
Isso significa ler as mensagens de erro com cuidado e completamente antes de agir para que você entenda o que está tentando lhe dizer. Ao depurar, faça as seguintes perguntas mentais, nesta ordem , ao ler uma mensagem de erro:
nil
? ) No rastreamento da pilha, preste atenção especial às linhas de código que vêm do seu projeto (por exemplo, linhas começando com app/...
se você estiver usando o Rails). 99% das vezes o problema está no seu próprio código.
Para ilustrar por que a interpretação nesta ordem é importante ...
Você executa um código que, em algum momento, é executado da seguinte maneira:
@foo = Foo.new
...
@foo.bar
e você recebe um erro que afirma:
undefined method "bar" for Nil:nilClass
Os iniciantes veem esse erro e pensam que o problema é que o método não bar
está definido . Não é. Nesse erro, a parte real que importa é:
for Nil:nilClass
for Nil:nilClass
significa que @foo
é nulo! @foo
não é uma Foo
variável de instância! Você tem um objeto que é Nil
. Quando você vê esse erro, é simplesmente ruby tentando dizer que o método bar
não existe para objetos da classe Nil
. (bem, duh! já que estamos tentando usar um método para um objeto da classe Foo
não Nil
).
Infelizmente, devido à forma como esse erro é escrito ( undefined method "bar" for Nil:nilClass
), é fácil ser enganado ao pensar que esse erro tem a ver com o bar
ser undefined
. Quando não é lido com atenção, esse erro faz com que os iniciantes, por engano, procurem nos detalhes do bar
método Foo
, perdendo totalmente a parte do erro que sugere que o objeto é da classe errada (neste caso: nulo). É um erro que é facilmente evitado com a leitura completa das mensagens de erro.
Resumo:
Sempre leia cuidadosamente toda a mensagem de erro antes de iniciar qualquer depuração. Isso significa que: Sempre verifique a classe tipo de um objeto em uma mensagem de erro primeira , em seguida, seus métodos , antes de começar a sleuthing em qualquer stacktrace ou linha de código onde você acha que o erro pode estar ocorrendo. Esses 5 segundos podem economizar 5 horas de frustração.
tl; dr: Não aperte os olhos para imprimir logs: crie exceções ou use um depurador irb. Evite buracos de coelho lendo os erros cuidadosamente antes de depurar.
Imprima as variáveis sempre que possível. (Isso é chamado de depuração printf) Você pode fazer isso executando
STDERR.puts x.inspect
ou
STDERR.puts "Variable x is #{x.inspect}"
Se você quiser fazer isso mais fácil de escrever, então você pode querer usar o exemplor jóia.
Ative os avisos. Se você estiver executando ruby
, execute-o com o -w
interruptor (por exemplo ruby -w script.rb
). Se você estiver executando o irb e estiver usando uma versão do ruby anterior à 1.9.2, digite $VERBOSE = true
no início da sua sessão. Se você digitar incorretamente uma variável de instância, quando os avisos estiverem ativados, você obterá
aviso: variável de instância
@valeus
não inicializada
Entenda o conceito de uma divisão binária (a citação a seguir é de Práticas de um desenvolvedor ágil )
Divida o espaço do problema ao meio e veja qual metade contém o problema. Em seguida, divida a metade pela metade novamente e repita.
Se você for bem-sucedido com uma costela binária, poderá achar que há uma única linha que não faz o que você espera. Por exemplo
[1, 2, 3].include?([1,2])
dá um valor de false
, mesmo que você pense que retornaria true
. Nesse caso, você pode querer consultar a documentação. Os sites da Web para documentação incluem ruby-doc.org ou APIdock . Nesse último caso, você digitaria include?
próximo à lupa no canto superior direito, escolheria o include?
que está Array
embaixo (se você não souber qual [1, 2, 3]
é a classe , digite [1, 2, 3].class
irb) e poderá incluir? (Matriz) , que descreve o que faz.
No entanto, se a documentação não ajudar, é mais provável que você obtenha uma boa resposta se puder fazer uma pergunta sobre como uma linha específica não está fazendo o que deveria, e não por que um script inteiro não está fazendo o que deveria.
apaga todas as coisas
Bem-vindo a 2017 ^ _ ^
Ok, se você não se opõe a experimentar um novo IDE, pode fazer o seguinte gratuitamente .
launch.json
para usar "cwd"
e e "program"
campos usando a {workspaceRoot}
macro"showDebuggerOutput"
e defina-o comotrue
"debug.allowBreakpointsEverywhere": true
vscode
; isso não é o mesmo que o Visual Studio . É grátis, leve e geralmente considerado positivamente.View->Extensions
.vscode
e lá vamos apenas um arquivo chamado launch.json
onde vamos armazenar algumas opções de configuração.
launch.json
conteúdo
{
"version": "0.2.0",
"configurations":
[
{
"name": "Debug Local File",
"type":"Ruby",
"request": "launch",
"cwd": "${workspaceRoot}",
"program": "{workspaceRoot}/../script_name.rb",
"args": [],
"showDebuggerOutput": true
}
]
}
File->Preferences->Settings
(ou Ctrl,) e rolamos até chegar à Debug
seção. Expanda-o e procure um campo chamado "debug.allowBreakpointsEverywhere"
- selecione esse campo e clique no pequeno ícone de lápis e defina-o como true
.Depois de fazer todas essas coisas divertidas, você poderá definir pontos de interrupção e depurar em um menu semelhante a este para meados de 2017 e um tema mais sombrio: com todas as coisas divertidas, como sua pilha de chamadas, visualizador variável etc.
A maior PITA é 1) instalar as pré-solicitações e 2) Lembre-se de configurar o .vscode\launch.json
arquivo. Somente o número 2 deve adicionar bagagem a projetos futuros, e você pode copiar uma configuração genérica o suficiente, como a listada acima. Provavelmente existe um local de configuração mais geral, mas não sei de nada.
Eu recomendo fortemente este vídeo, a fim de escolher a ferramenta adequada no momento para depurar nosso código.
https://www.youtube.com/watch?v=GwgF8GcynV0
Pessoalmente, eu destacaria dois grandes tópicos neste vídeo.
Esses são meus dois centavos!
Todas as outras respostas já dão quase tudo ... Apenas uma pequena adição.
Se você deseja um depurador mais semelhante ao IDE (não CLI) e não tem medo de usar o Vim como editor, sugiro o plugin Vim Ruby Debugger para ele.
Sua documentação é bastante direta, então siga o link e veja. Em resumo, ele permite que você defina o ponto de interrupção na linha atual no editor, visualize as variáveis locais na janela bacana em pausa, avance / avance - quase todos os recursos usuais do depurador.
Para mim, foi bastante agradável usar esse depurador vim para depurar um aplicativo Rails, embora as habilidades ricas em logger do Rails quase eliminem a necessidade dele.
Acabei de descobrir esta gema (transforma Pry em um depurador para MRI Ruby 2.0+)
https://github.com/deivid-rodriguez/pry-byebug
Instale com:
gem install pry-byebug
use exatamente como pry
, marque a linha em que deseja quebrar:
require 'pry'; binding.pry
Ao contrário de baunilha de alavanca no entanto, esta jóia tem algumas GDB-como navegação comandos de teclas, como next
, step
e break
:
break SomeClass#run # Break at the start of `SomeClass#run`.
break Foo#bar if baz? # Break at `Foo#bar` only if `baz?`.
break app/models/user.rb:15 # Break at line 15 in user.rb.
break 14 # Break at line 14 in the current file.
-w
sinalizador (avisos)irb
é um ótimo ponto de partida. Tente usar o irb com pequenos pedaços questionáveis. Eu amo o ruby-debug (ruby-debug19 para Ruby 1.9+) porque facilita parar o programa em execução, examinar variáveis, acessar o irb e continuar em execução.
Para depurar facilmente o script do shell Ruby, basta alterar sua primeira linha de:
#!/usr/bin/env ruby
para:
#!/usr/bin/env ruby -rdebug
Sempre que o console do depurador for exibido, você poderá escolher:
c
para Continuar (para a próxima exceção, ponto de interrupção ou linha com:) debugger
,n
para a próxima linha,w
/ where
para Quadro de exibição / pilha de chamadas,l
para mostrar o código atual,cat
para mostrar pontos de captura.h
para mais ajuda.Consulte também: Depurando com ruby-debug , Atalhos de chave para a ruby-debug gem .
Caso o script seja interrompido e você precise de um backtrace, tente usar lldb
/ gdb
como:
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
e verifique o primeiro plano do processo.
Substitua lldb
por gdb
se funciona melhor. Prefixo com sudo
a depuração do processo que não é de propriedade.
A partir do Ruby 2.4.0, é mais fácil iniciar uma sessão do IRB REPL no meio de qualquer programa Ruby. Coloque estas linhas no ponto do programa que você deseja depurar:
require 'irb'
binding.irb
Você pode executar o código Ruby e imprimir variáveis locais. Digite Ctrl + D ou quit
para finalizar o REPL e deixar o programa Ruby continuar em execução.
Você também pode usar puts
e p
imprimir valores do seu programa enquanto ele está sendo executado.
Se você estiver usando RubyMine , a depuração de scripts ruby é simples e direta.
Suponha que você tenha um script Ruby hello_world.rb
Defina um ponto de interrupção na linha 6 como abaixo.
Agora você pode simplesmente iniciar o depurador para executar o script:
Então, quando a execução atingir um ponto de interrupção, você poderá inspecionar variáveis etc.
depuração printf
Sempre houve uma controvérsia em torno das técnicas de depuração, algumas pessoas gostam de depurar por instruções impressas, outras gostam de se aprofundar em um depurador.
Eu sugiro que você tente as duas abordagens.
Na verdade, um dos antigos homens do Unix disse recentemente, que a depuração do printf era uma maneira mais rápida de ele em alguns momentos.
Mas se você é novo em algum trabalho e precisa entender um grande blob de código, é realmente útil avançar por lá, colocando alguns pontos de interrupção aqui e ali, acompanhando como ele funciona.
Isso deve lhe dar uma compreensão de como o código é tecido.
Se você é novo em algum software de outras pessoas, pode ajudá-lo a avançar por lá.
Você descobrirá rapidamente se eles organizaram de uma maneira inteligente ou se isso é apenas um monte de merda.
Bem, a ruby standard lib possui um depurador de console do tipo gdb fácil de usar: http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html Não é necessário instalar nenhuma gema extra. Os scripts do Rails também podem ser depurados dessa maneira.
por exemplo
def say(word)
require 'debug'
puts word
end
A mãe de todo o depurador é uma simples tela de impressão antiga. Na maioria das vezes, você provavelmente só deseja inspecionar alguns objetos simples, uma maneira rápida e fácil é a seguinte:
@result = fetch_result
p "--------------------------"
p @result
Isso imprimirá o conteúdo do @result para STDOUT com uma linha na frente para facilitar a identificação.
Bônus, se você usar uma estrutura capaz de carregar / recarregar automaticamente, como o Rails, nem precisará reiniciar seu aplicativo. (A menos que o código que você está depurando não seja recarregado devido a configurações específicas da estrutura)
Acho que isso funciona para 90% do caso de uso para mim. Você também pode usar o ruby-debug, mas acho que é um exagero na maioria das vezes.
Existem muitos depuradores com recursos diferentes, com base nos quais você faz a escolha. Minhas prioridades foram satisfeitas com movimentos de alavanca que eram: