【问题标题】:python subprocess.call and pipes [duplicate]python subprocess.call和管道[重复]
【发布时间】:2018-02-17 10:52:34
【问题描述】:

我有一个脚本,我在其中尝试使用 subprocess.call 来执行一系列 shell 命令,但在执行时似乎省略了一些命令。

具体来说:

#!/usr/bin/python
import tempfile
import subprocess
import os
import re


grepfd, grepfpath = tempfile.mkstemp(suffix=".xx")
sedfd,  sedfpath  = tempfile.mkstemp(suffix=".xx")

# grepoutfile = open( grepfpath, 'w')
sedoutfile  = open( sedfpath,  'w' )

subprocess.call(['cp','/Users/bobby/Downloads/sample.txt', grepfpath])

sedcmd = [ 'sort', 
           grepfpath,
           '|', 
           'uniq',
           '|',
           'sed',
           '-e',
           '"s/bigstring of word/ smaller /"',
           '|',
           'column',
           '-t',
           '-s',
           '"=>"' ]

print "sedcmd = ", sedcmd
subprocess.call( ['ls', grepfpath ] )
subprocess.call( ['sort', '|', 'uniq' ], stdin = grepfd )
subprocess.call( sedcmd,  stdout = sedoutfile )

并将其生成为输出:

python d3.py

sedcmd = ['sort', /var/folders/3h/_0xwt5bx0hx8tgx06cmq9h_4f183ql/T/tmp5Gp0ff.xx', '|', 'uniq', '|', 'sed', '-e', '"s /bigstring of word/smaller /"', '|', 'column', '-t', '-s', '"=>"'] /var/folders/3h/_0xwt5bx0hx8tgx06cmq9h_4f183ql/T/tmp5Gp0ff.xx 排序:打开失败:|:没有这样的文件或目录
排序:无效选项--e 尝试使用 `sort --help' 获取更多信息。

第一个 'sort: open failed: |:No such file... 来自第一个子进程调用 ['sort','|','uniq'], stdin = grepfd ) 'sort: invalid option -- e .. 来自第二个子进程调用 (sedcmd)。

我已经看到很多在这种情况下使用管道的例子——那我做错了什么?
谢谢!

【问题讨论】:

  • 如果您尝试使用管道等外壳功能,则需要传递一个字符串(而不是列表)并设置shell=True。阅读subprocess 文档了解详细信息。

标签: python subprocess pipe


【解决方案1】:

因此,如果您想在命令中使用 shell 管道,您可以在子进程中添加 shell=True: 所以它会是这样的:

sedcmd = 'sort /var/folders/3h/_0xwt5bx0hx8tgx06cmq9h_4f183ql/T/tmp5Gp0ff.xx | uniq | sed -e "s/bigstring of word/ smaller /" | column -t -s "=>" '
subprocess.call(sedcmd, shell=True)

但要小心 shell=True强烈建议使用它:subprocess official documentation

因此,如果您想使用不带 shell=True 的管道,您可以在 stdout 中使用 subprocees.PIPE,下面是一个示例:stackoveflow answer

【讨论】:

    【解决方案2】:

    这是一个使用任意数量的管道运行命令的类:

    pipeline.py

    import shlex
    import subprocess
    
    class Pipeline(object):
        def __init__(self, command):
            self.command = command
            self.command_list = self.command.split('|')
            self.output = None
            self.errors = None
            self.status = None
            self.result = None
    
        def run(self):
            process_list = list()
            previous_process = None
            for command in self.command_list:
                args = shlex.split(command)
                if previous_process is None:
                    process = subprocess.Popen(args, stdout=subprocess.PIPE)
                else:
                    process = subprocess.Popen(args,
                                               stdin=previous_process.stdout,
                                               stdout=subprocess.PIPE)
                process_list.append(process)
                previous_process = process
            last_process = process_list[-1]
            self.output, self.errors = last_process.communicate()
            self.status = last_process.returncode
            self.result = (0 == self.status)
            return self.result
    

    这个例子展示了如何使用这个类:

    harness.py

    from pipeline import Pipeline
    
    if __name__ == '__main__':
        command = '|'.join([
            "sort %s",
            "uniq",
            "sed -e 's/bigstring of word/ smaller /'",
            "column -t -s '=>'"
        ])
        command = command % 'sample.txt'
        pipeline = Pipeline(command)
        if not pipeline.run():
            print "ERROR: Pipeline failed"
        else:
            print pipeline.output
    

    我创建了这个示例文件来进行测试:

    sample.txt

    word1>word2=word3
    list1>list2=list3
    a>bigstring of word=b
    blah1>blah2=blah3
    

    输出

    a       smaller   b
    blah1  blah2      blah3
    list1  list2      list3
    word1  word2      word3
    

    【讨论】:

      猜你喜欢
      • 2015-06-09
      • 2013-05-05
      • 2013-03-02
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 2020-12-20
      • 2018-08-04
      • 1970-01-01
      相关资源
      最近更新 更多