【问题标题】:Capture Praat error messages resulting from sendpraat command in Python捕获由 Python 中的 sendpraat 命令产生的 Praat 错误消息
【发布时间】:2016-01-18 23:16:27
【问题描述】:

您可以启动一个 Praat 实例,然后使用sendpraat.exe 向它发送 GUI 命令。因此,如果您在后台运行 Praat,以下命令将导致它读取本地 mysound.wav 文件作为 Sound 对象:

sendpraat praat "Read from file... mysound.wav"

并且有很多方法可以通过 Python 发送此命令,例如:

import subprocess
subprocess.call('sendpraat praat "Read from file... mysound.wav"')

但是如果mysound.wav 不存在,Praat 实例会弹出一个错误消息框。如何在 Python 中捕获此错误消息的内容并避免弹出?

这些解决方案不适用于该问题:

  1. 对于这个特定的示例,如果文件存在,我可以只检查 Python。但我还需要处理 Praat 将抛出的所有其他错误,例如编码有问题或样本被剪裁时。

  2. 我可以在命令前使用nochecksendpraat praat nocheck "Read from file... mysound.wav" 来避免弹出窗口,但是 Python 无法知道命令失败。

【问题讨论】:

    标签: python windows ctypes praat


    【解决方案1】:

    nocheck 是 Praat 中进行错误处理的唯一方法,尽管它可能是有限的。如果您想通过 Python(或任何其他方式)以编程方式使用 GUI,进行错误处理的最佳方法是使用 nocheck,然后通过查找这些命令的副作用来捕获错误。

    如果您要打开 Sound,您可以执行 assert numberOfSelected("Sound") 或类似的操作(或多或少优雅的测试)。如果您正在向磁盘写入内容,您可以使用fileReadable() 查看文件是否已创建。

    或者,如果您实际上使用 GUI,您可以完全绕过 sendpraat 并通过控制台使用 Praat(对于 6.0 之前的版本,Windows 需要一个名为 praatcon 的不同二进制文件,但更新的版本使用带有--run 选项的相同程序。

    您将无法直接将命令传递给它,但您可以将这些命令封装到脚本中,然后执行subprocess.call('praat --run path/to/my/script.praat arguments') 或类似的操作。然后,您可能能够使用 Python 捕获该脚本(=您的命令)中的错误,或者实现与上述相同的手动错误检查。

    更新:一个例子

    这是一个例子(在 Perl 和 Linux 中,但你明白了):

    #!/usr/bin/env perl
    
    use Capture::Tiny ':all';
    use Try::Tiny;
    
    try {
      ($stdout, $stderr, $exit) = capture {
        system( 'praat', '--run', '~/stdout.praat' );
      }
    }
    catch {
      chomp;
      warn "It died: $_";
    };
    
    print "STDOUT:\n$stdout\n";
    print "STDERR:\n$stderr";
    

    还有stdout.praat的内容:

    abc$ = "abcde"
    num$ = "0123456789"
    writeInfoLine: abc$
    assert selected("Sound")  ; Fail
    writeInfoLine: abc$, num$ ; Won't run
    

    输出:

    user@linux:~$ perl stdout.pl
    STDOUT:
    abcde
    
    STDERR:
    Error: No Sound selected.
    Formula not run.
    Script line 4 not performed or completed:
    « assert selected("Sound") ; Fail »
    Script “/home/user/stdout.praat” not completed.
    Praat: command file “/home/user/stdout.praat” not completed.
    

    更新:Praat 中的 try / catch

    自从我写了这个答案,我已经设法实现了一个非常基本的a try/catch procedure for Praat 版本。有了它,像

    这样的脚本
    include path/to/try.proc
    
    writeInfoLine: "Before fail"
    
    call try
      ... abc$ = "abcde"                                \n
      ... num$ = "0123456789"                           \n
      ... Create Sound as pure tone: "tone",            \n
      ...   ... 1, 0, 0.4, 44100, 440, 0.2, 0.01, 0.01  \n
      ... assert selected("TextGrid")  ; Fail           \n
      ... Remove                       ; Won't run      \n
    
    if try.catch
      appendInfoLine: "Failed!"
    endif
    

    将在不崩溃的情况下执行,留下由于删除它的行没有运行而创建的声音。

    该过程在通过CPrAN分发的utils插件中可用,并在here实现。

    【讨论】:

    • 你知道是否有办法将 Praat 错误发送到 stderr 或类似的东西?我喜欢praatcon 解决方案,但这意味着每次运行脚本都会运行一个新的 Praat 实例。
    • Praat(和 Praatcon)应该将它的错误打印到 STDERR(当然,它会在它死之前这样做)。直到最近,Praatcon 中的一个错误意味着打印到 STDOUTSTDERR would not work,但这已通过 5.4.13 修复。我将用一个如何工作的例子来更新我的答案,但请注意:它不会是 Python。
    • 根据您的任务,您可以通过将较大脚本的部分逻辑包含到 praat 脚本中来减少运行 praat 的次数。这不会每次都有效,但它是一些东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多