Генерация сообщений в Mathematica

В модуле, который я пишу, у меня есть (для фаз разработки и тестирования) много Print["Messages"], У меня есть два вопроса:

  1. Как лучше печатать такие "отладочные" сообщения?
  2. Можно ли вызвать модуль так, чтобы сообщения НЕ печатались? Например, при вызове модуля из другого модуля я бы не хотел видеть все выходные данные первого.

5 ответов

Мне нравится всегда держать глобальные переменные с префиксом $ и функционирует без префикса, поэтому я бы написал:

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 позволяет использовать глобальные переменные относительно безопасным и контролируемым образом.

Мой старый код использует метод, который описывает Pillsy.

Совсем недавно я использовал голову, которая обычно не имеет никаких правил, например:

...
debugPrint[expr]
...

а затем есть вторая функция:

Attributes[PrintDebug]={HoldAll}

PrintDebug[expr_] := Block[{debugPrint = Print}, expr]

Затем, когда я хочу увидеть результаты отладки, я могу обернуть PrintDebug вокруг ввода:

PrintDebug[MyFunction[1,2,3]]

или чаще

MyFunction[1,2,3] // PrintDebug

поскольку я считаю, что постфиксную форму легче добавлять / удалять и лучше оставить основной упор на основной функции.

Я обычно устанавливаю в своих функциях многословную опцию, которую можно включить / выключить при необходимости для отладки. Обратите внимание, что указав значение по умолчанию для 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 -> ...] заголовок, а затем доступ к опциям внутри функции, но здесь дело не в этом.

Еще одна возможность:

debugPrint::msg = "Debug message: `1`";    
debugPrint[msg_] := Message[debugPrint::msg, msg]

Используйте функцию как это:

debugPrint["hello"]

Выключите или включите такие сообщения:

Off[debugPrint::msg]

On[debugPrint::msg]

Для меня, поскольку у M нет встроенного отладчика, о котором можно говорить, я трачу 50% своего времени только на отладку, которую можно было бы сэкономить, если бы был отладчик. 50% моего кода разработки составляют операторы Print, так как без них я потеряюсь, обнаружив, откуда исходит ошибка. (это также плохо, так как слишком большое количество печатных сообщений в коде иногда затрудняет просмотр алгоритма, он мешает, но не может удалить его, поскольку он может понадобиться мне позже).

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

Кто-то может сказать, использовать Workbench для отладки. Я попытался использовать для отладки демонстрации Manipulate, и я не могу понять это. Слишком сложный в использовании. M нуждается в простой простой в использовании встроенной программе отладчика (в самой записной книжке, а не в отдельной программе) и с номерами строк!

Хорошо, учитывая приведенное выше введение:), это то, что я делаю сам в ответ на ваш вопрос:

  1. имеют разные уровни отладочных сообщений. грубый уровень и уровень детализации. Грубый уровень печатает только сообщение, когда оно входит в функцию и когда она существует в функции.

  2. У меня есть кнопка в пользовательском интерфейсе для включения / выключения отладки (если вы делаете программу, основанную на пользовательском интерфейсе, иначе она будет в коде).

  3. Используйте отдельную функцию отладки, где отладочное сообщение проходит перед печатью. Там вы можете добавить отметку времени к каждому сообщению и тому подобное перед печатью (также можете контролировать, хотите ли вы, чтобы сообщения отправлялись в текстовый файл из одного места). Остальная часть вашего кода, просто вызывает эту функцию отладки с сообщением для печати. Теперь я печатаю все на консоли, а не на текущей записной книжке.

  4. Каждое отладочное сообщение имеет имя функции, которая вызывала его при запуске.

  5. Если вы хотите контролировать отладку на уровне модуля, то, что я делаю, это просто делает локальный флаг отладки внутри модуля и включаю / выключаю его каждый раз, когда я хочу отладить этот конкретный модуль. Этот локальный флаг отладки принимает настройку глобального флага отладки. Таким образом, я могу отлаживать только один модуль, если я хочу, а не остальную часть кода.

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

Вот несколько полезных ссылок

http://reference.wolfram.com/mathematica/guide/TuningAndDebugging.html

отладчик рабочей среды (если вы можете понять, как использовать для отладки Manipulate и Dynamics, пожалуйста, дайте мне знать)

http://www.wolfram.com/products/workbench/features/debug.html

Другие вопросы по тегам