Генерация сообщений в Mathematica - PullRequest
7 голосов
/ 02 января 2012

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

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

Ответы [ 5 ]

12 голосов
/ 25 февраля 2011

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

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

8 голосов
/ 25 февраля 2011

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

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

...
debugPrint[expr]
...

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

Attributes[PrintDebug]={HoldAll}

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

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

PrintDebug[MyFunction[1,2,3]]

или, чаще,

MyFunction[1,2,3] // PrintDebug

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

6 голосов
/ 02 января 2012

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

3 голосов
/ 02 января 2012

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

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

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

debugPrint["hello"]

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

Off[debugPrint::msg]

On[debugPrint::msg]
0 голосов
/ 02 января 2012

Для меня, поскольку у 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...