#! /usr/bin/python # Help creation of command pipelines # # Copyright (C) 2008 Vincent Legoll # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. 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 """ # We explicitely want to use keyword argument expansion, # so ask pylint to shut up about that # pylint: disable-msg=W0142 # 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()