Как отлаживать скрипты на Ruby [закрыто]

153

Я скопировал следующий код Ruby из Интернета и внес несколько изменений, но он не работает.

Что я могу сделать, чтобы отладить программу самостоятельно?

Эндрю Гримм
источник
1
Голосование возобновить. OP явно хочет GDB-подобную пошаговую отладку.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

145

Используйте Pry ( GitHub ).

Установить через:

$ gem install pry
$ pry

Затем добавьте:

require 'pry'; binding.pry

в вашу программу.

Начиная с pry0.12.2, однако, нет никаких навигационных команд, таких как next, breakи т. Д. Некоторые другие драгоценные камни дополнительно предоставляют это, см. Например pry-byedebug.

horseyguy
источник
10
Я также рекомендую использовать Pry (это определенно меняет жизнь!). После установки и использования в вашей программе установка точки останова так же проста, как и написание binding.pry. Он также поставляется с завершением цвета, поиском документации и возможностью динамически редактировать и перезагружать метод.
Андреа Фиоре
5
Домашняя страница Прай доступна здесь: pryrepl.org .
shadowbq
4
Pry/ byebugотлично, но не как ваш первый шаг при отладке. В большинстве случаев raise object.inspectвызов исключения с помощью решит вашу проблему быстрее, чем открытие сеанса irb. Я рекомендую использовать консольные отладчики только после того, как более простые решения, такие как создание исключения, не смогут решить вашу проблему.
Келси Ханнан
3
Есть ли способ пошагового кода с помощью pry? Я не мог найти, как это сделать; и это то, что я ожидаю от отладчика.
jpetazzo
2
@jpetazzo да, набрав «следующий»
marcbest
114
  1. В рубине:

    ruby -rdebug myscript.rb 

    затем,

    • b <line>: поставить точку останова
    • и n(ext)или s(tep)иc(ontinue)
    • p(uts) для отображения

    (как Perl отладки)

  2. В Rails: Запустите сервер с

    script/server --debugger

    и добавьте debuggerв код.

germanlinux
источник
7
rdebug это мусор. И не поддерживается. Используйте Прай (см. Другой ответ).
Snowcrash
3
@SnowCrash - Почему вы говорите, что -r debugэто мусор?
Сид Смит
8
с -rdebug: нет необходимости изменять исходный файл для отладки
germanlinux
2
Для нового приложения Ruby / Rails Pry - правильный ответ. Но я потратил более часа, пытаясь найти древнюю версию Pry для запуска в приложении Rails 2.2 с определенной версией facetsв требованиях к гемам, но безуспешно. Для древних Rails-приложений ruby-debugэто немного неприятно, но выполняет свою работу.
Абэ Фолькер
56

В качестве перил рекомендуется: использовать монтировку! Я могу только согласиться с этим.

Pry гораздо лучше, чем IRB.

Вам нужно добавить

require 'pry'

в исходный файл, а затем вставьте точку останова в исходный код, добавив

binding.pry

в месте, где вы хотите взглянуть на вещи (это похоже на срабатывание точки останова в классической среде IDE)

Как только ваша программа попадет в

binding.pry

линия, вы будете брошены прямо в pry repl, со всем контекстом вашей программы под рукой, так что вы можете просто исследовать все вокруг, исследовать все объекты, изменять состояние и даже изменять код на лету.

Я считаю, что вы не можете изменить код метода, в котором вы сейчас находитесь, поэтому вы, к сожалению, не можете изменить следующую строку для выполнения. Но хороший код ruby ​​в любом случае имеет тенденцию быть одной строкой ;-)

EDX
источник
30

Отладка путем повышения исключений является гораздо проще , чем щурясь черезprintзаявление журнала, и для большинства ошибок, его обычно гораздо быстрее , чем открытие КРПА отладчикакакpryилиbyebug. Эти инструменты не всегда должны быть вашим первым шагом.


Быстрая отладка Ruby / Rails:

1. Быстрый метод: поднять Exceptionпотом и .inspectего результат

Самый быстрый способ отладки кода Ruby (особенно Rails) - raiseэто исключение по пути выполнения вашего кода при вызове .inspectметода или объекта (например foo):

raise foo.inspect

В приведенном выше коде raiseзапускается функция,Exception которая останавливает выполнение вашего кода и возвращает сообщение об ошибке, которое удобно содержит .inspectинформацию об объекте / методе (т.е. foo) в строке, которую вы пытаетесь отладить.

Этот метод полезен для быстрого изучения объекта или метода ( например, так nilли это ? ) И для немедленного подтверждения того, выполняется ли вообще строка кода в данном контексте.

2. Откат: используйте отладчик ruby IRB, например byebugилиpry

Только после того, как вы получите информацию о состоянии потока выполнения ваших кодов, вы должны рассмотреть возможность перехода к отладчику ruby ​​gem irb, например, pryили byebugкуда вы сможете более глубоко погрузиться в состояние объектов в вашем пути выполнения.


Генеральный совет для начинающих

Когда вы пытаетесь отладить проблему, хороший совет: всегда читайте! @ # $ Ing Сообщение об ошибке (RTFM)

Это означает, что вы должны внимательно и полностью прочитать сообщения об ошибках, прежде чем действовать, чтобы вы поняли, что он пытается вам сказать. При отладке задайте следующие умственные вопросы в этом порядке при чтении сообщения об ошибке:

  1. К какому классу относится ошибка? (т.е. у меня есть правильный класс объекта или это мой объект nil? )
  2. На какой метод ссылается ошибка? (т.е. является ли это типом в методе; могу ли я вызвать этот метод для этого типа / класса объекта? )
  3. Наконец, используя то, что я могу вывести из моих последних двух вопросов, какие строки кода мне следует исследовать? (помните: последняя строка кода в трассировке стека не обязательно лежит там, где проблема.)

В трассировке стека обратите особое внимание на строки кода, которые приходят из вашего проекта (например, строки, начинающиеся с того, app/...что вы используете Rails). В 99% случаев проблема связана с вашим собственным кодом.


Чтобы проиллюстрировать, почему перевод в этом порядке важен ...

Например, сообщение об ошибке Ruby, которое смущает многих начинающих:

Вы выполняете код, который в какой-то момент выполняется так:

@foo = Foo.new

...

@foo.bar

и вы получите сообщение об ошибке:

undefined method "bar" for Nil:nilClass

Новички видят эту ошибку и думают, что проблема в том, что метод barне определен . Это не. В этой ошибке реальная часть, которая имеет значение:

for Nil:nilClass

for Nil:nilClassзначит это @fooноль! @fooне является Fooпеременной экземпляра! У вас есть объект, который есть Nil. Когда вы видите эту ошибку, просто ruby ​​пытается сказать вам, что метод barне существует для объектов класса Nil. (ну, да! Так как мы пытаемся использовать метод для объекта класса Fooнет Nil).

К сожалению, из-за того, как написана эта ошибка ( undefined method "bar" for Nil:nilClass), легко обмануться, думая, что эта ошибка связана с barбытием undefined. Если не читать внимательно, эта ошибка заставляет начинающих по ошибке копаться в деталях barметода Foo, полностью пропуская ту часть ошибки, которая намекает на то, что объект принадлежит к неправильному классу (в данном случае: nil). Эту ошибку легко избежать, прочитав сообщения об ошибках полностью.

Резюме:

Всегда внимательно читайте все сообщение об ошибке перед началом любой отладки. Это означает: всегда проверяйте тип класса объекта в сообщении об ошибке сначала , а затем его методы , прежде чем начинать переходить к любой трассировке стека или строке кода, где, по вашему мнению, может происходить ошибка. Эти 5 секунд могут сэкономить вам 5 часов разочарования.

tl; dr: не щуриться при печати журналов: генерировать исключения или использовать вместо этого отладчик irb. Избегайте кроличьих ям, внимательно читая ошибки перед отладкой.

Келси Ханнан
источник
3
Хотя я согласен с вами, что чтение журналов печати утомительно, я думаю, что рекомендация не использовать отладчик, во-первых, очень плохой совет. Добавление точки останова и ее запуск - это то же самое, что и создание исключения, но дает вам полное представление о текущем состоянии приложения. Если в результате проверки сомнительного состояния возникнут дополнительные вопросы, вы можете в интерактивном режиме перейти к детализации, вместо добавления еще одного исключения и перезапуска приложения.
Патрик Р.
2
@PatrickR. По моему опыту, отладчики IRB не являются хорошим первым шагом, когда вы все еще пытаетесь детализировать, где именно находится проблема в вашем коде. Добавление и удаление многих точек прерывания IRB занимает больше времени, чем добавление исключений, и не дает однозначных ответов о потоке управления вашего кода так, как исключения могут с новичками отсеять неверные предположения. О точках прерывания IRB также легко забыть, что приводит к путанице при зависании запросов. Если вы точно знаете , где находится проблема, и вам необходимо отладить ее состояние, тогда обязательно начните с отладчика IRB. Но часто это не так.
Келси Ханнан
1
Хах! Чтение сообщений об ошибках полезно для Ruby, но для других языков сценариев? Я не могу винить ОП в том, что он даже не беспокоил.
kayleeFrye_onDeck
1
Моя первоначальная реакция была похожа на @PatrickR., Но я все равно попробовал. В конце концов, я нахожу это плохим советом, или, возможно, в лучшем свете, советом, приспособленным к другому варианту использования, чем у меня. В частности, в случае, когда (a) не используется Rails и (b) получен неправильный результат, но нет ошибок или исключений, то есть код вычисляет число, это просто неправильное число. Попытка итеративно угадать, где создать программу, которая в противном случае выполняла бы сбой, является стратегией, но это больше работы, так как я должен продолжать перезапуск и повторный запуск. Каждый цикл имеет свое время запуска, которое теряется.
Кирпич
20
  1. Распечатайте переменные когда бы ни было возможно. (Это называется отладкой printf) Вы можете сделать это, запустив

    STDERR.puts x.inspect

    или

    STDERR.puts "Variable x is #{x.inspect}"

    Если вы хотите упростить ввод текста , вы можете использовать пример гема.

  2. Включите предупреждения. Если вы работаете, rubyзапустите его с помощью -wпереключателя (например ruby -w script.rb). Если вы запускаете его с irb и используете версию ruby ​​до 1.9.2, введите $VERBOSE = trueв начале сеанса. Если вы неправильно напишите переменную экземпляра, как только появятся предупреждения, вы получите

    предупреждение: переменная экземпляра @valeusне инициализирована

  3. Понять концепцию бинарной рубки (следующая цитата из « Практики гибкого разработчика» )

    Разделите проблемное пространство пополам и посмотрите, какая половина содержит проблему. Затем снова разделите эту половину пополам и повторите.

  4. Если вы добились успеха с бинарным отбиванием, вы можете обнаружить, что есть одна строка, которая не выполняет то, что вы ожидаете. Например

    [1, 2, 3].include?([1,2])

    дает значение false, даже если вы думаете, что он вернется true. В этом случае вы можете посмотреть документацию. Веб-сайты для документации включают ruby-doc.org или APIdock . В последнем случае вы печатаете include?рядом с увеличительным стеклом в верхнем правом углу, выбираете тот, include?который находится Arrayпод ним (если вы не знаете, что это за класс [1, 2, 3], введите [1, 2, 3].classirb), и вы можете включить его? (Массив) , который описывает, что он делает.

    Однако, если документация не помогает, вы, скорее всего, получите хороший ответ, если сможете задать вопрос о том, как конкретная строка не выполняет то, что должна, а не о том, почему весь сценарий не выполняет то, что нужно. должно.

Эндрю Гримм
источник
7

удаляет все вещи

Добро пожаловать в 2017 ^ _ ^

Итак, если вы не против попробовать новую IDE, вы можете сделать следующее бесплатно .

Быстрые Инструкции

  1. Установить vscode
  2. Установите Ruby Dev Kit, если вы еще этого не сделали
  3. Установите расширения для Ruby, ruby-linter и ruby-rubocop для vscode
  4. Вручную установите все, что указано в gems rubyide / vscode-ruby , при необходимости
  5. Настройте поля launch.jsonдля использования "cwd"и и "program" с помощью {workspaceRoot}макроса
  6. Добавьте поле с именем "showDebuggerOutput"и установите егоtrue
  7. Включите точки останова везде в ваших настройках отладки как "debug.allowBreakpointsEverywhere": true

Подробные инструкции

  1. Скачать Visual Studio Code aka vscode; это не то же самое, что Visual Studio . Это бесплатно, легкий и в целом положительно оценили.
  2. Установите Ruby Dev Kit; Вы должны следовать инструкциям на их репо здесь: https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
  3. Далее вы можете установить расширения либо через веб-браузер, либо внутри IDE; это для внутри IDE. Если вы выбираете другой, вы можете пойти сюда . Перейдите к части расширений vscode; Вы можете сделать это несколькими способами, но наиболее вероятный метод, вероятно, будет включать F1и печатать extдо тех пор , пока не станет доступной опция под названием Расширения: Установить расширения . Альтернативы CtrlShiftxи из верхней строки меню,View->Extensions
  4. Далее вам понадобятся следующие расширения; в этом нет необходимости на 100%, но я позволю вам решить, что оставить после того, как вы поработали:
    • Рубин; автор расширения Пэн Льв
    • рубиновый rubocop; расширение автор мисоги
    • рубиновый линт; автор расширения Cody Hoover
  5. Внутри каталога вашего ruby-скрипта мы создадим каталог через командную строку, .vscodeи там будет только файл с именем, в launch.jsonкотором мы будем хранить некоторые параметры конфигурации.
    • launch.json содержание

{ "version": "0.2.0", "configurations": [ { "name": "Debug Local File", "type":"Ruby", "request": "launch", "cwd": "${workspaceRoot}", "program": "{workspaceRoot}/../script_name.rb", "args": [], "showDebuggerOutput": true } ] }

  1. Следуйте инструкциям авторов расширений для ручной установки гемов. Сейчас он находится здесь: https://github.com/rubyide/vscode-ruby#install-ruby-dependencies
  2. Вы, вероятно, захотите возможность ставить точки останова, где хотите; Если эта опция не включена, это может привести к путанице. Для этого перейдем в верхнюю строку меню и выберите File->Preferences->Settings(или Ctrl,) и прокручивайте, пока не дойдете до Debugраздела. Разверните его и найдите поле с именем "debug.allowBreakpointsEverywhere"- выберите это поле и нажмите на маленький карандашоподобный значок и установите его в true.

Выполнив все эти забавные вещи, вы сможете установить точки останова и отладки в меню, похожем на это в середине 2017 года, и на более темную тему:введите описание изображения здесь со всеми забавными вещами, такими как стек вызовов, средство просмотра переменных и т. Д.

Самая большая PITA - это 1) установка предварительных требований и 2) запоминание конфигурации .vscode\launch.jsonфайла. Только # 2 должен добавить багаж в будущие проекты, и вы можете просто скопировать достаточно общий конфиг, как указано выше. Вероятно, есть более общее расположение конфигурации, но я не знаю, в верхней части моей головы.

kayleeFrye_onDeck
источник
Сейчас 2018 год, но, к сожалению, вы все еще не можете отладить модульное тестирование с помощью плагинов, которые вы перечислили здесь ... Довольно печально.
MonsieurDart
1
@MonsieurDart Когда я писал это, он предназначался для базовой отладки сценариев ruby. Я ничего не знаю конкретно о модульных тестах. Если этот ответ неверен или устарел, пожалуйста, дайте мне знать, что требует внимания, и любую информацию, которая может помочь ускорить этот процесс.
kayleeFrye_onDeck
Привет, @kayleeFrye_onDeck! Ваш ответ великолепен, я полностью вам это даю. Но в прошлый раз, когда я проверял плагин Ruby для VSC от Peng Lv, он не смог установить точки останова внутри юнит-теста (или любого другого теста). Это было одно из известных ограничений плагина. Я думаю, что люди должны знать это, прежде чем пытаться настроить свой экземпляр VSC: это требует времени, и для многих людей выполнение тестов является способом номер один для написания и отладки кода. M
MonsieurDart
6

Я настоятельно рекомендую это видео, чтобы выбрать подходящий инструмент для отладки нашего кода.

https://www.youtube.com/watch?v=GwgF8GcynV0

Лично я бы выделил две большие темы в этом видео.

  • Pry великолепен для отладочных данных, "pry - это проводник данных" (sic)
  • Отладчик, кажется, лучше отлаживать шаг за шагом.

Это мои два цента!

DavidSilveira
источник
6

Все остальные ответы уже дают почти все ... Просто небольшое дополнение.

Если вам нужен еще какой-нибудь IDE-подобный отладчик (не CLI) и вы не боитесь использовать Vim в качестве редактора, я предлагаю для него плагин Vim Ruby Debugger .

Его документация довольно проста, поэтому перейдите по ссылке и посмотрите. Короче говоря, он позволяет вам устанавливать точку останова в текущей строке в редакторе, просматривать локальные переменные в изящном окне на паузе, переходить / вставлять - почти все обычные функции отладчика.

Для меня было довольно приятно использовать этот отладчик vim для отладки приложения Rails, хотя богатые возможности Rails по ведению журналов почти исключают необходимость в нем.

NIA
источник
6

Я только что обнаружил этот драгоценный камень (превращает Прай в отладчик для MRI Ruby 2.0+)

https://github.com/deivid-rodriguez/pry-byebug

Установить с помощью:

gem install pry-byebug

затем используйте точно так же pry, отметьте строку, на которой вы хотите разбить:

require 'pry'; binding.pry

Однако, в отличие от vanilla pry, в этом геме есть несколько ключевых GDB-подобных навигационных команд, таких как next, stepи 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.
Нуреттин
источник
5
  1. Вы можете распечатать свои переменные по пути
  2. Включите -wфлаг (предупреждения)
  3. Используйте инструмент, такой как ruby-debug
ghostdog74
источник
2
Я добавлю, что irbэто отличная отправная точка. Попробуйте использовать irb с маленькими сомнительными кусками. Мне нравится ruby-debug (ruby-debug19 для Ruby 1.9+), потому что он позволяет легко остановить работающую программу, изучить переменные, перейти в irb и продолжить работу.
Жестянщик
5

Чтобы легко отлаживать скрипт оболочки Ruby, просто измените его первую строку с:

#!/usr/bin/env ruby

чтобы:

#!/usr/bin/env ruby -rdebug

Затем каждый раз, когда отображается консоль отладчика, вы можете выбрать:

  • c для продолжения (до следующего исключения, точки останова или строки с: debugger ,
  • n для следующей строки,
  • w/where Показать кадр / стек вызовов,
  • l Показать текущий код,
  • cat показать ловушки.
  • h для получения дополнительной справки.

Смотрите также: Отладка с помощью ruby-debug , Сочетания клавиш для гема ruby-debug .


Если скрипт просто зависает и вам нужна обратная трассировка, попробуйте использовать lldb/ gdblike:

echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)

а затем проверьте ваш процесс переднего плана.

Замените lldbна, gdbесли работает лучше. Префикс с sudoдля отладки не принадлежащего процессу.

kenorb
источник
1
ruby-debug выглядит довольно устаревшим. В репозитории git для ruby-debug есть только один коммит на этот год - он все еще активно поддерживается?
Эндрю Гримм
Он также поставляется в комплекте с рубином, и это здорово, когда вы в затруднении. Отличный ответ!
Breedly
5

Начиная с Ruby 2.4.0, легче начать сеанс IRB REPL в середине любой программы Ruby. Поместите эти строки в ту точку программы, которую вы хотите отладить:

require 'irb'
binding.irb

Вы можете запустить код Ruby и распечатать локальные переменные. Введите Ctrl + D илиquit чтобы завершить REPL и позволить программе Ruby продолжать работать.

Вы также можете использовать putsи pдля распечатки значений из вашей программы во время ее работы.

Дэвид Грейсон
источник
4

Если вы используете RubyMine , отладка скриптов ruby ​​проста и понятна.

Предположим, у вас есть скрипт на Ruby hello_world.rb

1. Установите точки останова

Установите точку останова в строке 6, как показано ниже.

введите описание изображения здесь

2. Начните отладку

Теперь вы можете просто запустить отладчик для запуска скрипта:

введите описание изображения здесь

введите описание изображения здесь

3. Проверьте переменные и т. Д.

Затем, когда выполнение достигнет точки останова, вы сможете проверить переменные и т. Д.

введите описание изображения здесь

Дополнительная информация для вашей справки

  1. Если вы хотите использовать RubyMine для удаленной отладки , вы можете сделать это.
  2. Если вы хотите использовать RubyMine для удаленной отладки, работающей внутри докера , это также просто.
Юйцы
источник
Есть ли у нас способ отладки внешних библиотек в RubyMine?
Am33d
2

отладка printf

Всегда существовали разногласия по поводу методов отладки, некоторым людям нравится отлаживать с помощью операторов печати, другим нравится копать глубоко с помощью отладчика.

Я бы посоветовал вам попробовать оба подхода.

На самом деле один из старых людей из Unix недавно сказал, что отладка printf была более быстрым способом добиться его в некоторых моментах.

Но если вы новичок в какой-то работе и вам нужно разбираться в большом куске кода, тогда действительно полезно пройтись туда, поставить некоторые точки останова здесь и там, и вместе с этим понять, как это работает.

Это должно дать вам некоторое представление о том, как создается код.

Если вы новичок в некоторых других программах, это может помочь вам пройти через это.

Вы быстро узнаете, устроили ли они это умным способом, или это просто куча дерьма.

EDX
источник
это, без сомнения, лучший ответ ,, это зависит
Menriquez
2

Ну, стандартная библиотека ruby ​​имеет простой в использовании gdb-подобный консольный отладчик: http://ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__.html Нет необходимости устанавливать дополнительные гемы. Сценарии Rails также могут быть отлажены таким образом.

например

def say(word)
  require 'debug'
  puts word
end
Форватер
источник
1

Мама всего отладчика - обычный старый экран печати. В большинстве случаев вы, вероятно, хотите осмотреть только несколько простых объектов, быстрый и простой способ выглядит так:

@result = fetch_result

p "--------------------------"
p @result

Это распечатает содержимое @result в STDOUT с линией впереди для легкой идентификации.

Бонус, если вы используете фреймворк с автозагрузкой / перезагрузкой, такой как Rails, вам даже не нужно будет перезапускать ваше приложение. (Если код, который вы отлаживаете, не перезагружается из-за специфических настроек фреймворка)

Я считаю, что это работает для 90% случаев использования для меня. Вы также можете использовать ruby-debug, но я нахожу это излишним в большинстве случаев.

Аарон Цянь
источник
1

Существует множество отладчиков с различными функциями, на основе которых вы делаете выбор. Мои приоритеты были удовлетворены любопытством, которое было:

  • быстро понятная информация о том, как использовать
  • интуитивно понятные шаги (например, легкий шаг в блоки)
  • «шаг назад» (подглядывание частично удовлетворяет потребность)
Даниэль Гармошка
источник