Генерация сообщений в математике
В модуле, который я пишу, у меня есть (для фаз разработки и тестирования) много Print["Messages"]
. У меня есть два вопроса:
- Какова наилучшая практика для печати таких сообщений "отладки"?
- Есть ли способ вызвать модуль таким образом, чтобы сообщения НЕ были напечатаны? Например, при вызове модуля из другого модуля я бы хотел не видеть все выходные данные первого.
Ответы
Ответ 1
Мне нравится всегда хранить глобальные переменные с префиксом $
и функции без префикса, поэтому я бы написал:
debugPrint[args___] := $debugPrintFunction[args]
$debugPrintFunction = Print[##] &
Тогда вы можете просто использовать debugPrint
точно так же, как вы бы использовали Print
сейчас. Когда вы хотите избавиться от отладочных сообщений, вы просто отключите переменную:
$debugPrintFunction = .
Есть несколько преимуществ для этого. Во-первых, вы можете использовать Block
для локального включения и выключения отладки:
In[1]:= foo[x_] := (debugPrint[x]; x+1)
In[2]:= foo[3]
3
Out[2]= 4
In[3]:= Block[{$debugPrintFunction}, foo[3]
Out[3]= 4
Вы можете даже локально сделать $debugPrintFunction
сделать что-то еще, например Sow
значения для Reap
, чтобы поднять или направить отладочные сообщения где-то еще, например
strm = OpenWrite["your/log/path/here", InputForm];
Block[{$debugPrintFunction = Write[strm, ##]},
foo[3]];
Close[strm];
Используется разумно, динамическое масштабирование, предоставляемое Block
, позволяет использовать глобальные переменные относительно безопасным и контролируемым образом.
Ответ 2
В моем старшем коде используется такой метод, как Pillsy.
В последнее время я использую голову, которая обычно не имеет никаких правил, например:
...
debugPrint[expr]
...
а затем вторую функцию:
Attributes[PrintDebug]={HoldAll}
PrintDebug[expr_] := Block[{debugPrint = Print}, expr]
Затем, когда я хочу увидеть вывод отладки, я могу обернуть PrintDebug вокруг ввода:
PrintDebug[MyFunction[1,2,3]]
или, чаще, как
MyFunction[1,2,3] // PrintDebug
так как я нашел постфиксную форму легче добавить/удалить и лучше оставить фокус на основной функции.
Ответ 3
Обычно я устанавливаю опцию verbosing в мои функции, которые могут быть включены/выключены, если необходимо для отладки. Обратите внимание, что, указав значение по умолчанию для Verbose внутри функции, вы можете контролировать, печатается ли информация или нет.
In[5]:= func1[arg_, opts___] := Module[{verbose},
verbose = Verbose /. {opts} /. {Verbose -> True};
If[verbose, Print["Verbosing function1: arg is ", arg]];
arg
];
func2[arg_, opts___] := Module[{verbose},
verbose = Verbose /. {opts} /. {Verbose -> False};
func1[arg, Verbose -> verbose]
];
In[7]:= func1[123]
During evaluation of In[7]:= Verbosing function1: arg is 123
Out[7]= 123
In[8]:= func2[456]
Out[8]= 456
In[9]:= func1[123, Verbose -> False]
Out[9]= 123
In[10]:= func2[456, Verbose -> True]
During evaluation of In[10]:= Verbosing function1: arg is 456
Out[10]= 456
Конечно, этот пример можно привести в соответствие с стандартами программирования Mathematica (например, добавить заголовок Options[func1, Verbose -> ...]
, а затем получить доступ к опциям изнутри функции, но здесь дело не в этом.
Ответ 4
Еще одна возможность:
debugPrint::msg = "Debug message: `1`";
debugPrint[msg_] := Message[debugPrint::msg, msg]
Используйте функцию следующим образом:
debugPrint["hello"]
Отключить или включить такие сообщения:
Off[debugPrint::msg]
On[debugPrint::msg]
Ответ 5
Для меня, поскольку у M нет встроенного отладчика, о котором я говорю, я трачу 50% своего времени только на отладку, которая могла быть сохранена, если был отладчик. 50% моего кода разработки - это операторы печати, так как без них я буду потерян, найдя, откуда исходит ошибка. (это тоже плохо, так как слишком много печатных сообщений в коде затрудняет просмотр алгоритма когда-то, он мешает, но не может его удалить, поскольку он может понадобиться позже).
Мне кажется удивительным, что такой мощный и гибкий вычислительный инструмент, как M, все еще имеет относительно менее развитую среду разработки. Когда я использую Matlab, мне нужно несколько секунд, чтобы найти ошибку, используя отладчик.
Кто-то может сказать, что Workbench для отладки. Я попытался использовать отладочную демонстрацию Manipulate, и я не могу понять это. Слишком сложно использовать. M нуждается в простой простой в использовании отладчик (в самом ноутбуке, а не в отдельной программе) и с номерами строк!
Хорошо, учитывая приведенное выше введение:), это то, что я сам делаю в ответ на ваш вопрос:
-
имеют разные уровни отладочных сообщений. грубый уровень и подробный уровень. Грубый уровень печатает только сообщение, когда оно входит в функцию и когда существует функция.
-
У меня есть кнопка в пользовательском интерфейсе для включения/выключения отладки (если вы используете программу на основе пользовательского интерфейса, иначе она будет в коде).
-
Используйте отдельную функцию отладки, в которой происходит отладочное сообщение перед печатью. Там вы можете добавить отметку времени к каждому сообщению и тому подобное перед печатью (также можете управлять, если вы хотите, чтобы сообщения отправлялись в текстовый файл, из одного места). Остальная часть кода просто вызывает эту функцию отладки с сообщением для печати. Я печатаю все сейчас, чтобы консоль, а не текущий ноутбук.
-
Каждое отладочное сообщение имеет имя функции, которое вызывало его при его запуске.
-
Если вы хотите контролировать отладку на уровне модуля, что я делаю, он просто создает локальный флаг отладки внутри модуля и каждый раз, когда я хочу отлаживать этот конкретный модуль, включаю его/выключать. Этот локальный флаг отладки принимает параметр глобального флага отладки. Таким образом, я могу отлаживать только один модуль, если хочу, а не остальную часть кода.
Есть много других способов настроить все это. Но я обнаружил, что если я потрачу больше времени на то, чтобы создать хорошую систему сообщений для отладки, это поможет выделить ошибки при необходимости.
Вот полезная ссылка
http://reference.wolfram.com/mathematica/guide/TuningAndDebugging.html
отладчик workbench (если вы можете понять, как использовать debug Manipulate и Dynamics, сообщите мне)
http://www.wolfram.com/products/workbench/features/debug.html