pexpect / ptyprocess

Run a subprocess in a pseudo terminal
https://ptyprocess.readthedocs.io/en/latest/
Other
217 stars 71 forks source link

is it possible to PtyProcess.read() without blocking? #48

Open sentriz opened 5 years ago

sentriz commented 5 years ago

I'm running ptyprocess in read in a greenlet coroutine. so when I .read() and there's no data, it blocks and stops all the other greenlets. is it possible to read without blocking, or at least check if there's any new data?

Sorry it this is a silly question

Thank you

takluyver commented 5 years ago

Pexpect has a read_nonblocking method:

https://github.com/pexpect/pexpect/blob/831052254a039531adc91ebfce945d9ca54fd00a/pexpect/pty_spawn.py#L415

axgkl commented 5 years ago

gevent's tp_read also works:

term.pty = PtyProcessUnicode.spawn(term.cmd, env=env, cwd=opts.get("cwd", None))

and then

    def from_pty(wsock_xtermjs_observer):
        while True:
            b = gevent_os.tp_read(term.pty.fd, 65536).decode("utf-8")
            wsock_xtermjs_observer.on_next(["stdout", b])

works like a charm, i.e. does not block other greenlets with gevent_os = gevent.os.

Other more manual method would be using gevent.select, i.e. before read you check:

readable, _, _ = select.select([pty.fd], [], [], timeout)

PS: No silly question, my kids did not get their fairytale yesterday evening, because of this :-/

sentriz commented 5 years ago

@AXGKl wow, that works very nicely. thank you very much. :)

one thing though: how are you detecting when the process has ended / there is no data left, so you can break the while True?

from the docs "If end-of-file is reached, an empty string is returned.", and based on that, the following is not working:

while True:
    # proc is an instance of PtyProcessUnicode
    data = gevent_os.tp_read(proc.fd, 65536)
    if not data:
        break
    use(data)

because I get a OSError: [Errno 5] Input/output error on my second line when the program has quit (I think because the file desriptor is closed) so we never reach the if not data

I've tried

while not proc.closed:
    data = gevent_os.tp_read(proc.fd, 65536)
    use(data)

but it's the same issue

thank you very much