#! /usr/bin/python from subprocess import Popen, PIPE def pipeline(*pipe_cmds, **kw): """Create a pipeline of processes connected together by their standard inputs and outputs. You can pass additional named parameters, the same as for subprocess.Popen() objects, they will be passed through to the pipeline subprocesses. Exceptions are for stdin and stdout: stdin is only passed to the first process in the pipeline stdout is only passed to the last process in the pipeline return subprocess.Popen() object of the last process in the pipeline. You should call communicate() to start the processing For example: >>> print pipeline(["ls", "-d", "/"], ["wc", "-l"], stdout = PIPE).communicate()[0] 1 >>> print pipeline(["echo", "1:2:3"], ["cut", "-d:", "-f2"], stdout = PIPE).communicate()[0] 2 """ # Backup stdout, as it is for the last process in the pipeline only # Default of None is exactly the behaviour we want here, if it is not # passed in, the file descriptor will be inherited from parent process stdout = kw.get('stdout') # We're building first stages of the pipeline connected together kw['stdout'] = PIPE # Create the processes, keeping track of their stdout for the next # process. for cmd in pipe_cmds[:-1]: p = Popen(cmd, **kw) kw['stdin'] = p.stdout # Restore backuped stdout for the last stage kw['stdout'] = stdout # End of the pipeline handled manually since we cannot reassign # p.stdout after Popen() call return Popen(pipe_cmds[-1], **kw) def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test()