2012-01-02 8 views
7

En un módulo que estoy escribiendo tengo (para las fases de desarrollo y prueba) un montón de Print["Messages"]. Tengo dos preguntas:Generación de mensajes en mathematica

  1. ¿Cuál es la mejor práctica para imprimir tales mensajes de "depuración"?
  2. ¿Hay alguna manera de llamar al módulo para que se impriman los mensajes NOT? Por ejemplo, cuando llamo al módulo desde otro módulo, me gustaría no ver todo el resultado del primero.
+2

En v.8, también hay 'Assert' que es similar en cuanto imprime el mensaje en el fallo de la prueba, y se puede desactivar –

+0

@Verbeia Sí, es cierto ... Pensé que las dos preguntas son tan cercanas que sería beneficioso fusionarlas y tener todas respuestas en el mismo lugar Ya sea que ese se haya fusionado en este o en el revés, no importa ... – Szabolcs

+0

@Szabolcs vea el mensaje para usted en el chat – Verbeia

Respuesta

12

me gusta mantener siempre las variables globales con el prefijo $ y funciones sin el prefijo, por lo que me gustaría escribir:

debugPrint[args___] := $debugPrintFunction[args] 

$debugPrintFunction = Print[##] & 

A continuación, sólo se puede utilizar debugPrint exactamente igual que tendría que utilizar Print ahora. Cuando se quiere deshacerse de los mensajes de depuración, que acaba de desactivar la variable:

$debugPrintFunction = . 

Hay algunas ventajas de hacerlo de esta manera. Una de ellas es que se puede utilizar Block para cambiar la depuración de encendido y apagado localmente:

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 

Incluso se puede hacer a nivel local $debugPrintFunction hacer otra cosa, como Sow valores para una Reap para recoger, o dirigir los mensajes de depuración en otro lugar, como

strm = OpenWrite["your/log/path/here", InputForm]; 
Block[{$debugPrintFunction = Write[strm, ##]}, 
    foo[3]]; 
Close[strm]; 

utilizarse con prudencia, el ámbito dinámico proporcionado por Block permite el uso de variables globales de una manera relativamente segura y controlada.

+0

Buenos trucos. Me quedaron sin votos, pero votaré tan pronto como se reponga la bolsa. –

+0

Eso es increíble, muchas gracias. –

8

Mi código anterior usa un método como Pillsy describe.

Más recientemente he utilizar una cabeza que normalmente no tiene ningún reglas, como:

... 
debugPrint[expr] 
... 

y luego tener una segunda función:

Attributes[PrintDebug]={HoldAll} 

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

Luego, cuando quiero ver la salida de depuración que puede envolver alrededor de la entrada de PrintDebug:

PrintDebug[MyFunction[1,2,3]] 

o, más frecuentemente como

MyFunction[1,2,3] // PrintDebug 

porque encuentro que el formulario de postfix es más fácil de agregar/eliminar y lo mejor es dejar el foco en la función principal.

0

Para mí, dado que M no tiene un depurador incorporado, desperdicio el 50% de mi tiempo solo en la depuración, que podría haberse guardado si hubiera un depurador. El 50% de mi código de desarrollo son instrucciones de impresión, ya que sin ellas, estaré perdido para encontrar de dónde viene un error. (Esto también es malo, ya que demasiados mensajes de impresión en el código hacen que sea difícil ver el algoritmo en algún momento, se pone en el camino, pero no puede eliminarlo, ya que podría necesitarlo más adelante).

Me parece sorprendente que una herramienta de cómputo tan poderosa y flexible como M, todavía tenga un entorno de desarrollo relativamente menos avanzado. Cuando uso Matlab, me lleva unos segundos encontrar dónde está el error, usando el depurador.

Alguien podría decir usar Workbench para la depuración. Intenté usar para depurar una demostración Manipulate, y no puedo resolverlo. Demasiado complicado de usar. M necesita una compilación de depurador simple y fácil de usar (en el propio cuaderno, no en un programa separado) y con números de línea.

Ok, teniendo en cuenta la introducción anterior :), esto es lo que hago yo en respuesta a su pregunta:

  1. tienen diferentes niveles de mensajes de depuración. nivel grueso, y nivel detallado. El nivel aproximado imprime solo un mensaje cuando ingresa una función y cuando existe la función.

  2. Tengo un botón en la IU para usar para activar/desactivar la depuración (si está haciendo un programa basado en UI, de lo contrario estará en el código).

  3. Utilice una función de depuración separada, donde se envía el mensaje de depuración antes de imprimirse. Allí, puede agregar un sello de tiempo a cada mensaje y demás antes de imprimir (también puede controlar si desea que los mensajes vayan al archivo de texto, desde un solo lugar). Resto de su código, simplemente llama a esta función de depuración con el mensaje para imprimir. Imprimo todo ahora en consola, no en el portátil actual.

  4. Cada mensaje de depuración tiene el nombre de la función que lo llamó al inicio.

  5. Si desea controlar la depuración a nivel de módulo, lo que hago, simplemente crea un indicador de depuración local dentro del Módulo y lo enciendo/apaga cada vez que quiero depurar ese módulo específico. Esta bandera de depuración local asume la configuración del indicador de depuración global. De esta forma, puedo depurar solo un módulo si quiero, y no el resto del código.

Hay muchas otras maneras de personalizar todo esto. Pero descubrí que si dedico más tiempo desde el principio a crear un buen sistema de mensajes de depuración, me ayuda a encontrar errores cuando es necesario.

Éstos son algunos vínculo útil

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

banco de trabajo depurador (si puede averiguar cómo utilizar para depurar manipular y dinámica, por favor hágamelo saber)

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

+3

Para aclarar, Mathematica * does * tiene un depurador incorporado, donde puede establecer el punto de interrupción, entrar en el código, etc. Aunque es un poco incómodo de usar, está ahí. 'Evaluación -> Depurador' – Szabolcs

+0

@Szabolcs, sí, sé de eso. Pero, ¿es realmente útil? Me paso puede ser de 2 horas en el otro día, y ni siquiera podía imaginar cómo usarlo para depurar mi cuaderno Manipular. Al final, me di por vencido, y volví a imprimir mensajes :) – Nasser

+2

Mucha gente podría encontrar esta pregunta y respuesta, y pensé que es engañoso para ellos afirmar que no hay un depurador. Es cierto que no lo uso mucho, y que no es terriblemente práctico, pero sí lo uso ocasionalmente. – Szabolcs

3

Sin embargo, otro posibilidad:

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

Uso de la función como esta:

debugPrint["hello"] 

activar o desactivar mensajes de la siguiente manera:

Off[debugPrint::msg] 

On[debugPrint::msg] 
6

por lo general se instala una opción verbosing en mis funciones, que se pueden activar/desactivar si es necesario para depuración Tenga en cuenta que al especificar el valor predeterminado para Detallado dentro de la función, puede controlar si la información se imprime o no.

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 

Por supuesto, uno puede elaborar este ejemplo que cumple con los estándares de programación de Mathematica (por ejemplo, la adición de la cabecera Options[func1, Verbose -> ...] y luego acceder a las opciones desde el interior de la función, pero este no es el punto aquí.

+1

Puede encontrar también útil el siguiente contruct __verbose && Imprimir ["Verbosing function1: arg is", arg] __ en lugar del IF. –

+0

Ese es un atajo inteligente, me ahorra una gran cantidad de combinaciones de corchetes, ¡gracias! –