【问题标题】:SBCL bypass debugger and print error for display in other environment?SBCL 绕过调试器并打印错误以在其他环境中显示?
【发布时间】:2019-06-12 03:24:30
【问题描述】:

我通过环境 MaxMSP 的 shell 命令控制 SBCL。

通常我的命令是: sbcl --core some/path/to/a/.core/file --script my/script/generated/in/max

一切都很好,除非发生错误...... 在那种情况下,我没有得到任何结果,而且除了在 SBCL 调试器出现的终端中评估相同的命令外,我也无法知道出了什么问题。

有没有办法只为这个评估禁用调试器——如果遇到错误通常会放弃——然后“回显”错误的实际内容?

通常会得到类似的实际字符串 “价值 '多多 不是类型 数字 绑定 SB-KERNEL::X" 时,所以我可以直接从 Max 中看到它并转到终端?

感谢您的帮助! 最好的,

朱利安

我尝试在我的命令之上添加 --non-interactive,它有帮助,但它绝对不是我需要的。

似乎我应该以某种方式使用 debug-io 但我不确定如何访问它的内容:(

【问题讨论】:

    标签: error-handling runtime-error common-lisp sbcl


    【解决方案1】:

    你可以尝试使用--disable-debugger:

    $ echo '(error "Oh no")' > script.lisp 
    $ sbcl --disable-debugger --load $PWD/script.lisp 
    This is SBCL 1.5.2.33-d415e2949, an implementation of ANSI Common Lisp.
    More information about SBCL is available at <http://www.sbcl.org/>.
    
    SBCL is free software, provided as is, with absolutely no warranty.
    It is mostly in the public domain; some portions are provided under
    BSD-style licenses.  See the CREDITS and COPYING files in the
    distribution for more information.
    While evaluating the form starting at line 1, column 0
      of #P"/tmp/script.lisp":
    Unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                        {10005C85B3}>:
      Oh no
    
    Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005C85B3}>
    0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SIMPLE-ERROR "Oh no" {1003643C33}> #<unused argument> :QUIT T)
    1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<SIMPLE-ERROR "Oh no" {1003643C33}>)
    2: (INVOKE-DEBUGGER #<SIMPLE-ERROR "Oh no" {1003643C33}>)
    3: (ERROR "Oh no")
    4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (ERROR "Oh no") #<NULL-LEXENV>)
    5: (EVAL-TLF (ERROR "Oh no") 0 NIL)
    6: ((LABELS SB-FASL::EVAL-FORM :IN SB-INT:LOAD-AS-SOURCE) (ERROR "Oh no") 0)
    7: ((LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) (ERROR "Oh no") :CURRENT-INDEX 0)
    8: (SB-C::%DO-FORMS-FROM-INFO #<CLOSURE (LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) {10036436CB}> #<SB-C::SOURCE-INFO {1003643683}> SB-C::INPUT-ERROR-IN-LOAD)
    9: (SB-INT:LOAD-AS-SOURCE #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/script.lisp" {1003641C13}> :VERBOSE NIL :PRINT NIL :CONTEXT "loading")
    10: ((FLET SB-FASL::THUNK :IN LOAD))
    11: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<CLOSURE (FLET SB-FASL::THUNK :IN LOAD) {7F13FE6777EB}> #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/script.lisp" {1003641C13}>)
    12: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/script.lisp" {1003641C13}> NIL)
    13: (LOAD #P"/tmp/script.lisp" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
    14: (SB-IMPL::PROCESS-EVAL/LOAD-OPTIONS ((:LOAD . "/tmp/script.lisp")))
    15: (SB-IMPL::TOPLEVEL-INIT)
    16: ((FLET SB-UNIX::BODY :IN SAVE-LISP-AND-DIE))
    17: ((FLET "WITHOUT-INTERRUPTS-BODY-14" :IN SAVE-LISP-AND-DIE))
    18: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))
    

    请注意,跟踪已打印,然后程序退出。

    或者,您可以将*DEBUGGER-HOOK* 设置为在进入调试器时调用的自定义函数,例如,您可以在其中打印错误并调用(sb-ext:quit)

    例如:

    (setf *debugger-hook*
          (lambda (condition old-hook)
            (declare (ignore old-hook))
            (format *error-output*
                     "Caught error: ~a"
                     condition)
            (finish-output *error-output*)
            (sb-ext:quit)))
    

    如果您更喜欢在脚本中使用HANDLER-CASE,代码几乎相同:

    (handler-case (...main...)
      (condition (c) ...log and quit..))
    

    【讨论】:

    • 这就是问题所在,我不想定义自己的错误信息,我想检索 Lisp 本身产生的错误信息,你知道有什么方法吗?
    • 如果有关于 MaxMSP 的公开文档,我很乐意阅读。但是如果你直接写一些东西到query-io,会发生什么?如果一个简单的打印确实将文本发送到 GUI widhget,那么您只需要使用一个处理程序案例包装您的代码,该处理程序案例可以捕获任何错误并将其打印在该流中。您是否有更多关于 MaxMSP 工作原理的信息?看起来很有趣。
    • 是的,这一切都已记录在案,但可能不值得为您深入研究,它是主要用于音乐家的专有软件(可视化编程)。有一个“shell”第三方对象可以用来以某种方式与 mac 的终端交互——我想这是某种仿真。但我不使用它的实际结果:我使用它来评估调用 SBCL 的脚本,并将它自己的结果写入临时文件(with-open-file 等)。但似乎每当发生错误时,SBCL 调试器只会中断所有内容并且不会真正“打印”它。 query-io 也无济于事
    • 假设shell是github.com/jeremybernstein/shell,看起来你只能用stdout和stderr流来传递结果,这对应于standard-outputerror-output 在 Lisp 中。您可能需要捕获所有错误(请参阅gigamonkeys.com/book/…)并将它们记录到 error-output,然后退出。
    • 哇,谢谢,你成功了!实际上,在您建议的 Seibel 章节之后,我不确定(在我的水平上)如何捕捉这些错误。但你真的让我走对了:在 Bernstein 的对象中我错过了一个小帮助文件,它解释了如何在 Max 的打印结果中将错误输出附加到标准输出。它不是很干净,但我设法从调试器中过滤了我不需要的所有内容,并隔离了我需要的错误字符串。再次感谢你 !最好的,朱利安
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 2020-04-19
    相关资源
    最近更新 更多