Как я могу проверить, есть ли в stdin входные данные в julia? - PullRequest
4 голосов
/ 31 марта 2020

Я хотел бы определить, есть ли входные данные на stdin в коротком временном окне, и продолжить выполнение в любом случае, с результатом, сохраненным в Bool. (Моя настоящая цель состоит в том, чтобы внедрить кнопку паузы в симуляцию, которая запускается в терминале. Повторное нажатие клавиши должно отменить выполнение программы и продолжить выполнение.) Я пытался использовать poll_fd, но она не работает на stdin:

julia> FileWatching.poll_fd(stdin, readable=true)
ERROR: MethodError: no method matching poll_fd(::Base.TTY; readable=true)

Есть ли способ, который будет работать на Джулию? Я нашел решение, которое работает в python, и я подумал об использовании этого через PyCall, но я ищу

  1. более чистый, чисто-юлианский способ; и
  2. способ, который не борется и не может помешать использованию Юлией libuv.

Ответы [ 2 ]

5 голосов
/ 31 марта 2020
bytesavailable(stdin)

Вот пример использования. Обратите внимание, что если вы захватываете клавиатуру, вам также нужно обрабатывать Ctrl + C самостоятельно (в этом примере проверяется только первый байт фрагмента).

Если вы хотите запустить ее полностью асинхронно, вставьте @async в передняя часть while l oop. Однако, если в этом случае больше не будет кода, эта программа просто закроется.

import REPL
term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
REPL.Terminals.raw!(term,true)
Base.start_reading(stdin)

while (true)
    sleep(1)
    bb = bytesavailable(stdin)
    if bb > 0
        data = read(stdin, bb)
        if data[1] == UInt(3)
            println("Ctrl+C - exiting")
            exit()
        end
        println("Got $bb bytes: $(string(data))")
    end
end
0 голосов
/ 01 апреля 2020

Следуя ответу @Przemyslaw Szufel, вот полное решение, позволяющее нажатию клавиши приостанавливать / отменять итерацию al oop:

import REPL
term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
REPL.Terminals.raw!(term,true)
Base.start_reading(stdin)

function read_and_handle_control_c()
    b = bytesavailable(stdin)
    @assert b > 0
    data = read(stdin, b)
    if data[1] == UInt(3)
        println("Ctrl+C - exiting")
        exit()
    end
    nothing
end

function check_for_and_handle_pause()
    if bytesavailable(stdin) > 0
        read_and_handle_control_c()
        while bytesavailable(stdin) == 0
            sleep(0.1)
        end
        read_and_handle_control_c()
    end
    nothing
end

while true
    # [do stuff]
    sleep(0.05)
    check_for_and_handle_pause()
end

Это несколько неоптимально, поскольку требует, чтобы процесс регулярно просыпаюсь, даже когда пауза, но, тем не менее, он достигает моей цели.

...