- #INTERRUPT BASED SER AIL READINGIN PYTHON FOR MAC OS CODE#
- #INTERRUPT BASED SER AIL READINGIN PYTHON FOR MAC OS WINDOWS#
It pumps at same time and stdout and stderr in almost correct order. Here is my code, used to catch every output from subprocess ASAP, including partial lines.
Hopefully this can be helpful to other readers, even if it isn't applicable for your particular application. On the other hand, if your program isn't built on top of Twisted, this isn't really going to be that helpful. If you build your entire application around Twisted, it makes asynchronous communication with other processes, local or remote, really elegant like this. The Twisted documentation has some good information on this. Reactor.spawnProcess(proc, './myprogram', ) A simple example demonstrating this behavior is as follows: from twisted.internet import protocol, reactorĬlass MyProcessProtocol(protocol.ProcessProtocol): So the outReceived() method is simply installing a callback for handling data coming from STDOUT. Twisted (depending upon the reactor used) is usually just a big select() loop with callbacks installed to handle data from different file descriptors (often network sockets). You create a ProcessProtocol class, and override the outReceived() method.
#INTERRUPT BASED SER AIL READINGIN PYTHON FOR MAC OS CODE#
Depending upon your existing code base, this might not be that easy to use, but if you are building a twisted application, then things like this become almost trivial. You can do this really easily in Twisted. read a line from subprocess' stdout asynchronouslyĮach step could be limited by timeout seconds if necessary.start subprocess, redirect its stdout to a pipe.Readline_and_kill() performs the following tasks: Sys.exit(n_until_complete(readline_and_kill(
Return await process.wait() # wait for the child process to exit Print("got line:", code(locale.getpreferredencoding(False))) # read line (sequence of bytes ending with b'\n') asynchronously Process = await asyncio.create_subprocess_exec(*args, stdout=PIPE) (with async/ await Python 3.5+ syntax): #!/usr/bin/env python3.5 There is a high-level interface asyncio.create_subprocess_exec() that returns Process objects that allows to read a line asynchroniosly using StreamReader.readline() coroutine n_until_complete(loop.subprocess_exec(SubprocessProtocol,
#INTERRUPT BASED SER AIL READINGIN PYTHON FOR MAC OS WINDOWS#
Loop = asyncio.ProactorEventLoop() # for subprocess' pipes on Windows The approach is similar to twisted-based answer by Ward - define a protocol and its methods are called as soon as data is ready: #!/usr/bin/env python3Ĭlass SubprocessProtocol(asyncio.SubprocessProtocol): Python 3.4 introduces new provisional API for asynchronous IO - asyncio module. In my opinion this is a bit cleaner than using the select or signal modules to solve this problem but then again it only works on UNIX. A solution I have found to this problem is to make stdin a non-blocking file using the fcntl module: import fcntlįcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) If the primary functionality is complete and there is no longer any need to wait for further user input I typically want my program to exit, but it can't because readline() is still blocking in the other thread waiting for a line. Simply putting the user input handling functionality in another thread doesn't solve the problem because readline() blocks and has no timeout. I have often had a similar problem Python programs I write frequently need to have the ability to execute some primary functionality while simultaneously accepting user input from the command line (stdin).