I'm trying to write a simple commandline wrapper: a script that runs another program as a child and relays unbuffered stdin and stdout to/from the child process, possibly filtering it.
The usefulness of such a program lies in the filtering stage, in a possible integration with readline, or in other interface enhancements. Still, I'd like to discuss with you the unfiltered, unembellished version, because I'm not satisfied with it and because I'm having some minor problems. Here's the script: #!/usr/bin/python import sys, os, thread def stdin_handler(child_stdin): while True: d = sys.stdin.read(1) if not d: break child_stdin.write(d) child_stdin.flush() child_stdin.close() def stdout_handler(child_stdout): while True: try: d = child_stdout.read(1) if not d: break sys.stdout.write(d) sys.stdout.flush() except KeyboardInterrupt: pass def wrap(cmd): child_stdin, child_stdout = os.popen2(cmd) thread.start_new_thread(stdin_handler, (child_stdin,)) stdout_handler(child_stdout) if __name__ == '__main__': wrap(sys.argv[1]) You invoke it passing a program name as the first argument (such as bash, python itself, sbcl, whatever) and then you interact with the child process as if this wrapper wasn't there. Ctrl-C and Ctrl-D work as expected, sending SIGINT (that the child program can catch) and closing stdin respectively. Problems: 1. I don't like the read(1) loops. I'd like to be able to read bigger chunks at a time, but I haven't found a way to do that while keeping the functionality intact. I have tried fidgeting with select() but I didn't get far. What I (think I) need is a non-blocking read(), but I'm not sure how to achieve that, at least with Python 2.4 on Linux. 2. Even this version sometimes has problems. For example, if you launch the wrapper around sbcl (a free Lisp interpreter/compiler) it mostly works (entering 1 gives 1, entering (+ 2 3) gives 5...) until you get to the debugger, for example by entering an undefined name. Now, when the debugger says "0: [ABORT] Exit debugger...", entering 0 should get you back to the "*" prompt--and indeed does, unless you are using my wrapper, in which case everything hangs, and the only solution is to terminate everything with Ctrl-\ or such. Any idea how to improve the script and solve this problem? Toby -- http://mail.python.org/mailman/listinfo/python-list