7 题: 检索subprocess.call()[duplicate]的输出

在...创建的问题 Tue, Jan 16, 2018 12:00 AM
    

这个问题已经有了答案:

    

如何使用subprocess.call()获取流程的输出?

StringIO.StringIO对象传递给stdout会出现此错误:

 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
    c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>> 
    
233
  1. Mike的回答是正确的。请注意,StringIO在大多数情况下像文件 但不是全部。它在您的情况下不起作用,因为multiprocessing模块在某些情况下会假定实际文件。这可能已经修复:请参阅 bugs.python.org/issue5313 了解相关错误。
    2010-01-03 22:16:51Z
  2. 实际上,communicate()使用select.select(),它只接受文件描述符,所以它实际上不是一个bug。当我第一次遇到它并探索subprocess.py的深度时,我对此非常困惑。教我很多!。
    2010-01-03 22:25:23Z
  3. 我认为 subprocess.run 使这更简单。当我有机会时,我会添加一个答案。
    2016-04-11 09:36:11Z
  4. 醇>
    7答案                              7 跨度>                         

    subprocess.call()的输出只应重定向到文件。

    您应该使用subprocess.Popen()。然后,您可以传递subprocess.PIPE作为stderr,stdout和/或stdin参数,并使用communicate()方法从管道中读取:

     
    from subprocess import Popen, PIPE
    
    p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    output, err = p.communicate(b"input data that is passed to subprocess' stdin")
    rc = p.returncode
    

    原因是subprocess.call()使用的类文件对象必须具有真实的文件描述符,因此实现了fileno()方法。只使用任何类似文件的对象都无法解决问题。

    有关详细信息,请参见此处

        
    183
    2014-05-06 12:33:11Z
    1. 此页面 docs .python.org /library /subprocess.html #module-subprocess 不鼓励使用subprocess.PIPE,任何想法如何克服这个?
      2011-12-13 20:55:41Z
    2. 此外,问题使用subprocess.call指定,Mike的回答实际上是使用Popen,因为subprocess.call只返回返回码,但没有访问任何一个流。如果使用2.6,如果使用2.7 @Sergi答案可以使用
      2012-11-12 12:17:18Z
    3. @ Halst:文档警告PIPE呼叫call()(在这种情况下不要使用PIPE)。如果答案显示,可以使用PIPEsubprocess.Popen,例如output, _ = Popen(..., stdout=PIPE).communicate()
      2014-01-10 22:42:10Z
    4. @ NathanBasanese:简而言之:除非您使用管道,否则不使用PIPEcall()Popen().wait(),因此它不消耗管道(一旦相应的OS管道缓冲区填充,子进程将永久挂起)。如果使用Popen().communicate(),则PIPE从管道写入/读取数据,从而允许子进程继续。
      2015-09-02 23:32:46Z
    5. //啊,好的。那讲得通。很奇怪它甚至是一个然后,将PIPE作为一个参数。无论如何,我是一个很好的StackOverFlow公民,并提出了一个问题: stackoverflow.com/questions/32364849 /... 你愿意把它作为答案吗?
      2015-09-02 23:41:35Z
    6. 醇>

    如果你有Python版本&gt; = 2.7,你可以使用 subprocess.check_output 基本上完全符合你的要求(它将标准输出作为字符串返回)。

    简单示例(linux版本,请参阅注释):

     
    import subprocess
    
    print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
    

    请注意,ping命令使用的是linux表示法(-c表示计数)。如果您在Windows上尝试此操作,请记住将其更改为-n以获得相同的结果。

    如下所示,您可以在其他答案中找到更详细的说明。

        
    236
    2018-03-08 07:40:18Z
    1. 找到另一个带有工作代码的答案。如果你使用它,请upvote。
      2012-07-19 13:17:34Z
    2. 但请注意,如果进程返回非零退出代码,check_output将抛出异常。
      2015-08-04 15:35:51Z
    3. 请注意,check_output因PIPE填充问题而遭遇run,因为它只是调用run。因此,如果您有一个生成更多输出的进程,它将无限期挂起。来自 @ Mike's Popen解决方案> @ Jabba的答案效果更好
      2017-05-26 03:26:46Z
    4. 但另一个答案没有演示如何从check_call读取stdout。
      2017-09-28 20:48:42Z
    5. 你应该把它放在你的答案中。
      2018-03-07 15:34:25Z
    6. 醇>

    我有以下解决方案。它还捕获退出代码,stdout和stderr执行的外部命令:

     
    import shlex
    from subprocess import Popen, PIPE
    
    def get_exitcode_stdout_stderr(cmd):
        """
        Execute the external command and get its exitcode, stdout and stderr.
        """
        args = shlex.split(cmd)
    
        proc = Popen(args, stdout=PIPE, stderr=PIPE)
        out, err = proc.communicate()
        exitcode = proc.returncode
        #
        return exitcode, out, err
    
    cmd = "..."  # arbitrary external command, e.g. "python mytest.py"
    exitcode, out, err = get_exitcode_stdout_stderr(cmd)
    

    我也有一篇博文这里

    编辑:解决方案已更新为不需要写入temp的新解决方案。文件。

        
    47
    2014-01-10 09:57:36Z
    1. 谢谢。很棒的答案。
      2014-02-09 15:04:43Z
    2. @ Jabba由于某种原因它不起作用,除非我将shell=True添加到Popen()的参数中,你能解释一下原因吗?
      2014-02-18 07:47:18Z
    3. @ JaeGeeTee:您想要呼叫的命令是什么?我的猜测是你想调用一个包含管道的命令(例如“cat file.txt | wc -l”)。
      2014-02-20 16:57:34Z
    4. @ Jabba我正在运行ping 127.0.0.1
      2014-02-20 23:15:00Z
    5. @JaeGeeTee - 尝试明确使用/bin /ping?
      2014-04-24 10:14:15Z
    6. 醇>

    对于python 3.5+,建议您使用子进程模块中的运行函数一>。这将返回一个CompletedProcess对象,您可以从中轻松获取输出以及返回代码。

     
    from subprocess import PIPE, run
    
    command = ['echo', 'hello']
    result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    print(result.returncode, result.stdout, result.stderr)
    
        
    40
    2016-01-21 17:13:40Z
    1. 这是一个很好的答案。但是不要忽视'stdout = PIPE'部分,就像我第一次做的那样,否则输出会非常短暂!
      2017-07-28 09:31:54Z
    2. 而不是universal_newlines=True,你应该使用text=True,因为前者是为了向后兼容而保留的。
      2019-05-08 11:34:16Z
    3. 醇>

    我最近刚刚想出了如何做到这一点,这里是我当前项目的一些示例代码:

     
    #Getting the random picture.
    #First find all pictures:
    import shlex, subprocess
    cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
    #cmd = raw_input("shell:")
    args = shlex.split(cmd)
    output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
    #Another way to get output
    #output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
    ber = raw_input("search complete, display results?")
    print output
    #... and on to the selection process ...
    

    现在您将命令的输出存储在变量“output”中。 “stdout = subprocess.PIPE”告诉该类在Popen中创建一个名为“stdout”的文件对象。从我所知道的,communication()方法只是一种方便的方法来返回输出的元组和你运行的进程的错误。此外,在实例化Popen时运行该过程。

        
    28
    2011-02-07 22:13:28Z
    1. 没有真正回答如何使用电话的问题(明智地说。)
      2017-09-28 20:51:06Z
    2. 醇>

    Ipython shell中:

     
    In [8]: import subprocess
    In [9]: s=subprocess.check_output(["echo", "Hello World!"])
    In [10]: s
    Out[10]: 'Hello World!\n'
    

    基于sargue的回答。归功于sargue。

        
    12
    2015-09-05 13:14:48Z
    1. 很高兴看到这里的例子。
      2017-09-28 20:54:43Z
    2. s=subprocess.check_output(["echo", "Hello World!"]); print(s)打印为b'Hello World!\n'我怎么能摆脱b''索引? @jhegedus
      2018-08-31 12:50:42Z
    3. 醇>

    以下在单个变量中捕获进程的stdout和stderr。它与Python 2和3兼容:

     
    from subprocess import check_output, CalledProcessError, STDOUT
    
    command = ["ls", "-l"]
    try:
        output = check_output(command, stderr=STDOUT).decode()
        success = True 
    except CalledProcessError as e:
        output = e.output.decode()
        success = False
    

    如果您的命令是字符串而不是数组,请在前面加上:

     
    import shlex
    command = shlex.split(command)
    
        
    7
    2019-01-21 21:48:26Z
    1. subprocess.check_output你的意思是。效果很好。最后,一个完成每个人实际期望的功能。
      2017-11-17 17:51:16Z
    2. @ sudo抱歉。忘记了导入语句
      2017-11-17 17:54:34Z
    3. Np,很容易搜索。顺便说一下,它还有一个input=选项来指定管道输入到命令,而不是使用Popen这样做超级复杂的方式。
      2017-11-17 22:16:42Z
    4. 很棒即使使用非零退出代码也可以使用它!
      2018-07-16 16:49:10Z
    5. @Matt编辑了导入
      2019-01-21 21:48:49Z
    6. 醇>
来源放置 这里