Simple process IO capture (Was: "shell-commands" and python!) - process.py (0/1)
Neil Schemenauer
nas at python.ca
Mon Sep 24 16:42:22 EDT 2001
Here's my humble attempt at a popen replacement. Note that it doesn't
use the shell (a feature IMHO) and it only works on Unix systems.
Suggestions for the module name are welcome. I would like to get
something like this in the standard library.
Neil
###########################################################################
# child_process.py
###########################################################################
import os
# created 2001/09/04, nas
class _ChildProcess:
"""
Instance attributes:
pid : int
the process id of the child process
stdin : file
open file connected to file descriptor 0 of the child process
stdout : file
open file connected to file descriptor 1 of the child process
stderr : file
open file connected to file descriptor 2 of the child process
"""
MAXFD = 256
def __init__(self, argv, bufsize=-1):
child_stdin, stdin = os.pipe()
stdout, child_stdout = os.pipe()
stderr, child_stderr = os.pipe()
self.stdin = os.fdopen(stdin, 'w', bufsize)
self.stdout = os.fdopen(stdout, 'r', bufsize)
self.stderr = os.fdopen(stderr, 'r', bufsize)
self.pid = os.fork()
if self.pid == 0:
os.dup2(child_stdin, 0)
os.dup2(child_stdout, 1)
os.dup2(child_stderr, 2)
for i in range(3, self.MAXFD):
try:
os.close(i)
except:
pass
try:
os.execvp(argv[0], argv)
finally:
os._exit(1)
os.close(child_stdin)
os.close(child_stdout)
os.close(child_stderr)
def read(self, n=-1):
"""Read from child stdout"""
return self.stdout.read(n)
def readline(self):
"""Readline from child stdout"""
return self.stdout.readline()
def readlines(self):
"""Readlines from child stdout"""
return self.stdout.readlines()
def write(self, s):
"""Write data to child stdin"""
self.stdin.write(s)
def flush(self):
"""Flush stdin pipe to child"""
self.stdin.flush()
def close(self):
"""Close stdin, stdout and stderr pipes to child process. Wait
for the exit status of the child and return it."""
for fd in (self.stdin, self.stdout, self.stderr):
if not fd.closed:
fd.close()
status = self.wait()
if status == 0:
return None # matches behavior of popen(...).close()
else:
return status
def wait(self, flags=0):
pid, status = os.waitpid(self.pid, flags)
return status
def execute(argv, bufsize=-1):
r"""execute(argv : (string*), bufsize=-1) -> _ChildProcess
Create a child process with pipes connected to its stdout, stdin and
stderr file descriptors. The child is created using fork() and
execvp() in order to avoid the argument quoting problems presented by
using system() or popen(). The bufsize argument has the same meaning as
for the open() builtin and applies to stdin, stdout, and stderr.
Examples:
>>> p = execute(("ls", "/"))
>>> p.readline()
'bin\n'
>>> p.readline()
'boot\n'
>>> p.close()
>>>
>>> p = execute(("cat",))
>>> p.write("hello world\n")
>>> p.stdin.close()
>>> p.read()
'hello world\n'
>>> p.close()
>>>
"""
return _ChildProcess(argv, bufsize)
More information about the Python-list
mailing list