【问题标题】:Detecting keystrokes in Julia在 Julia 中检测击键
【发布时间】:2014-05-11 14:46:10
【问题描述】:

我在 Julia 中有一段代码,其中求解器在寻找非常复杂问题的解决方案时会进行多次迭代。目前,我必须为代码提供多次迭代,设置足够低以至于我不必等待数小时让代码停止以保存当前状态,但足够高以至于我不需要必须保持每 5 分钟激活一次代码。

在 Julia (0.2) 的当前状态下,有没有办法检测一个击键,指示代码要么不保存就结束(以防出现问题),要么以保存结束?我需要一种方法,这样代码将继续畅通无阻,除非发生这样的击键事件,并且在任何迭代时都会中断。

本质上,我正在寻找一个命令,如果发生击键(当 Julia 正在运行的终端具有焦点时),它将读取击键,如果击键是特定键,则运行某些代码。这可能吗?

注意:我在 Xubuntu 上通过 xfce4-terminal 运行 julia,以防影响所需的命令。

【问题讨论】:

  • 你想做的是终端编程领域。它通常涉及修改当前的 tty,然后监听击键。我不知道 julia 中的任何软件包目前可以让你这样做。
  • 我找到了一种通过 Tk GUI 实现实现我想要的结果的方法,其中“保存”触发代码在下一次迭代中停止,“取消”触发错误以停止代码而不保存。我没有回答这个问题,因为我的解决方案没有提供检测击键的方法,并且需要为 Julia 提供击键检测方法。

标签: julia keystroke


【解决方案1】:

您可以使用异步任务从 STDIN 读取,阻塞直到有内容可供读取。在您的主要计算任务中,当您准备好检查输入时,您可以调用 yield() 为读取任务提供几个周期,并检查全局以查看是否读取了任何内容。例如:

input = ""
@async while true
    global input = readavailable(STDIN)
end
for i = 1:10^6 # some long-running computation                                  
    if isempty(input)
        yield()
    else
        println("GOT INPUT: ", input)
        global input = ""
    end
    # do some other work here                                                   
end

请注意,由于这是协作多线程,因此没有竞争条件。

【讨论】:

  • 感谢您的想法,但我似乎无法让它发挥作用。如果我让它以 1:10 循环并使其执行 reduce(*,1:big(500000)) 以在“在这里做一些其他工作”部分让它慢一点,然后在它运行时输入一些东西,它根本不会停止(对于输入,我的意思是 - 它只是运行直到完成处理)。如果定期运行和使用额外进程(julia -p 1)运行,这都是正确的。我正在使用 0.2.1 - 这可能是问题吗?
【解决方案2】:

您可以通过发送中断 (Ctrl+C) 来实现此目的。这应该可以在 REPL 中运行,而无需对您的代码进行任何更改 - 如果您想实现保存,则必须处理生成的 InterruptException 并提示用户。

【讨论】:

  • 有没有办法让代码从抛出异常的地方继续?没有类似的东西,我看不到如何处理在重要变量正在更新的过程中引发异常的情况。
  • 我认为唯一的方法是在这些点重复异常处理程序(也许使用宏来避免太多重复)。
【解决方案3】:

我在 steven-g-johnson 的回答中遇到了一些麻烦,最终使用 Channel 在任务之间进行通信:

function kbtest()
    # allow 'q' pressed on the keyboard to break the loop
    quitChannel = Channel(10)
    @async while true
        kb_input = readline(STDIN)
        if contains(lowercase(kb_input), "q")
            put!(quitChannel, 1)
            break
        end
    end

    start_time = time()
    while (time() - start_time) < 10
        if isready(quitChannel)
            break
        end

        println("in loop @ $(time() - start_time)")
        sleep(1)
    end

    println("out of loop @ $(time() - start_time)")
end

这需要按然后,这很适合我的需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多