Wolfram mathematica mathematica中的消息生成

Wolfram mathematica mathematica中的消息生成,wolfram-mathematica,messages,Wolfram Mathematica,Messages,在我正在编写的一个模块中,我(在开发和测试阶段)有很多打印[“消息”]。我有两个问题: 打印此类“调试”消息的最佳实践是什么 是否有办法调用模块,使信息不会被打印?例如,当从另一个模块调用该模块时,我不希望看到第一个模块的所有输出 我喜欢始终将全局变量的前缀设置为$,而将函数的前缀设置为不带前缀,因此我要写: debugPrint[args___] := $debugPrintFunction[args] $debugPrintFunction = Print[##] & 然后,您可

在我正在编写的一个模块中,我(在开发和测试阶段)有很多
打印[“消息”]
。我有两个问题:

  • 打印此类“调试”消息的最佳实践是什么
  • 是否有办法调用模块,使信息不会被打印?例如,当从另一个模块调用该模块时,我不希望看到第一个模块的所有输出

  • 我喜欢始终将全局变量的前缀设置为
    $
    ,而将函数的前缀设置为不带前缀,因此我要写:

    debugPrint[args___] := $debugPrintFunction[args]
    
    $debugPrintFunction = Print[##] &
    
    然后,您可以像现在使用打印一样使用
    debugPrint
    。如果要删除调试消息,只需取消设置变量:

    $debugPrintFunction = .
    
    这样做有一些好处。一种是,您可以使用在本地打开和关闭调试:

    您甚至可以在本地使
    $debugPrintFunction
    执行其他操作,如
    Sow
    值,以便
    获取
    或将调试消息定向到其他地方,如

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

    明智地使用,提供的动态作用域允许以相对安全和可控的方式使用全局变量。

    我以前的代码使用Pillsy描述的方法

    最近我使用了一个通常没有任何规则的头部,比如:

    ...
    debugPrint[expr]
    ...
    
    然后有第二个功能:

    Attributes[PrintDebug]={HoldAll}
    
    PrintDebug[expr_] := Block[{debugPrint = Print}, expr]
    
    然后,当我想要查看调试输出时,我可以将PrintDebug环绕在输入周围:

    PrintDebug[MyFunction[1,2,3]]
    
    或者更频繁地

    MyFunction[1,2,3] // PrintDebug
    

    因为我发现后缀表单更容易添加/删除,并且更好地将重点放在主函数上。

    对于我来说,因为M没有内置调试器,所以我将50%的时间浪费在调试上,如果有调试器的话,这本可以节省下来。我的开发代码中有50%是打印语句,因为如果没有这些语句,我将无法找到错误的来源。(这也是不好的,因为代码中有太多的打印消息,有时很难看到算法,它会造成阻碍,但无法删除,因为我以后可能需要它)

    我发现,像M这样强大而灵活的计算工具,仍然有一个相对不太先进的开发环境,这令人惊讶。当我使用Matlab时,使用调试器需要几秒钟才能找到bug所在的位置

    有人可能会说使用Workbench进行调试。我试图用它来调试一个操纵演示,但我想不出来。太复杂,无法使用。M需要一个简单易用的内置调试器(在笔记本中,而不是一个单独的程序),并带有行号

    好的,鉴于上述介绍:),以下是我自己对你问题的回答:

  • 具有不同级别的调试消息。粗略级别和详细级别。粗略级别仅在进入函数和存在函数时打印消息

  • 我在UI上有一个按钮用于打开/关闭调试(如果您正在执行基于UI的程序,否则它将出现在代码中)

  • 使用一个单独的调试功能,在打印调试消息之前,调试消息将经过该功能。在这里,您可以在打印前为每条消息添加时间戳(还可以控制是否希望消息从一个位置转到文本文件)。在代码的其余部分,只需调用此调试函数并打印消息。我现在将所有内容打印到控制台,而不是当前笔记本

  • 具有的每个调试消息都具有在其开始时调用它的函数名

  • 如果您想在模块级控制调试,我所做的只是在模块内创建一个本地调试标志,并在每次我要调试某个特定模块时打开/关闭该标志。此本地调试标志接管全局调试标志的设置。这样,如果需要,我可以只调试一个模块,而不调试其余的代码

  • 还有许多其他方法可以定制所有这些。但我发现,如果我在早期花更多的时间制作一个好的调试消息系统,它将有助于在需要时找到bug

    这里有一些有用的链接

    工作台调试器(如果您能了解如何使用调试操纵和动态,请告诉我)


    还有另一种可能性:

    debugPrint::msg = "Debug message: `1`";    
    debugPrint[msg_] := Message[debugPrint::msg, msg]
    
    使用如下函数:

    debugPrint["hello"]
    
    Off[debugPrint::msg]
    
    On[debugPrint::msg]
    
    关闭或打开以下消息:

    debugPrint["hello"]
    
    Off[debugPrint::msg]
    
    On[debugPrint::msg]
    

    我通常在函数中安装详细选项,如果调试需要,可以打开/关闭该选项。请注意,通过在函数中指定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的编程标准(例如,添加
    选项[func1,Verbose->…]
    标题,然后从函数内部访问选项,但这不是重点。

    很好的技巧。我的票数用完了,但我会在袋子装满后立即向上投票。在v.8中,还有一个类似的
    Assert
    ,它在测试失败时打印消息,并且可以打开off@Verbeia是的,没错……我只是虽然这两个问题非常接近,但将它们合并并将所有答案放在同一个位置将是有益的。无论这一个合并到这一个还是相反,这都无关紧要…@Szabolcs在聊天中为您查看消息只是为了澄清,Mathematica确实有一个内置的调试器,您可以在其中设置断点、进入代码等。虽然使用起来有点不方便,但它确实存在。
    评估->调试器
    @Szabolcs,是的,我知道这一点。但它真的实用吗?前几天我可能花了2个小时在它上,甚至不知道如何使用它来调试我的笔记本电脑。最后,我放弃了,重新开始打印消息:)很多人可能会遇到这个问题和答案,我认为他们说没有调试器是误导的。的确,我不经常使用它,而且它也不太实用,但我确实偶尔使用它