3

我正在尝试编写一个实用程序,它将在 Python 中无缝地将无限量的命令连接在一起。这是我到目前为止提出的,遵循管道中的文档subprocess

from subprocess import Popen, PIPE, STDOUT

def taskchain(argset, result=STDOUT):
    lastprocess = None

    for index, args in enumerate(argset): # expected to be a list containing lists
        process = Popen(args, stdout=stdout if index == (len(argset)-1) else PIPE,
            stdin=None if lastprocess is None else lastprocess.stdout)

        if lastprocess is not None:
            lastprocess.stdout.close()

        lastprocess = process

    if stdout == PIPE:
        return lastprocess.communicate()[0]
    else:
        lastprocess.wait()

请注意,我不是shell=True为了避免那里的安全问题而使用。

不幸的是,这不起作用,因为我得到:

OSError: [Errno 9] Baf file descriptor

我不确定什么似乎失败了。有人可以帮我编写一种方法来为无限数量的子流程实现流程链接吗?

(用例是这样的:taskchain([('ps', 'aux'), ('grep', 'python'), ('cut', '-b', '1')])。)

4

2 回答 2

2
stdout=stdout if argset.index(args) == (len(args) - 1) else PIPE)

这应该是

stdout=stdout if argset.index(args) == (len(argset) - 1) else PIPE)

你最好使用enumerate而不是argset.index.

此外,您需要将子流程相互连接:

..., stdin=None if lastprocess is None else lastprocess.stdout)

最后,STDOUT仅作为参数的实stderr参有效;要通过标准输出,您应该通过stdout=None.

于 2013-11-01T20:17:11.517 回答
0

在上面@ecatmur 的帮助下,这是最终的解决方案:

def taskchain(*args, **kwargs):
    output = kwargs.get('output', PIPE)
    error_output = kwargs.get('error_output', STDOUT) 
    lastprocess = None

    for index, argset in enumerate(args):
        islastprocess = index == len(args) - 1

        process = Popen(argset, stdout=output if islastprocess else PIPE,
                stdin=None if lastprocess is None else lastprocess.stdout,
                stderr=error_output)

        if lastprocess is not None:
            lastprocess.stdout.close()

        lastprocess = process

    if output == PIPE:
        return lastprocess.communicate()
    else:
        lastprocess.wait()

流程链接在一起,有效地模拟基于外壳的管道,没有安全风险!

例子:

>>> print taskchain(('ps','aux'), ('grep','python'), ('cut','-c','1-50'))[0].trim()
naftuli   3221  0.1  0.1  60960 12376 pts/3    S+ 
naftuli   3242  0.0  0.0  32592  5748 pts/2    S+ 
naftuli   3246  0.0  0.0   9388   916 pts/2    S+ 
naftuli   5852  0.0  0.2 430284 20200 ?        Sl 
root      8153  0.0  0.1  95520 11060 ?        S

>>> print taskchain(('ls',), ('grep', 'ic'))[0]
Music
Pictures
Public
于 2013-11-01T21:12:15.030 回答