Python subprocess: chaining commands with subprocess.run

和自甴很熟 提交于 2019-12-08 08:26:32

问题


I'm experimenting with subprocess.run in Python 3.5. To chain two commands together, I would have thought that the following should work:

import subprocess

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay'], stdin=ps1.stdout)

However, this fails with:

AttributeError: 'str' object has no attribute 'fileno'

ps2 was expecting a file-like object, but the output of ps1 is a simple string.

Is there a way to chain commands together with subprocess.run?


回答1:


Turns out that subprocess.run has an input argument to handle this:

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay'], universal_newlines=True, input=ps1.stdout)

Also, the following works as well, which doesn't use input:

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay', ps1.stdout], universal_newlines=True)



回答2:


subprocess.run() can't be used to implement ls | cowsay without the shell because it doesn't allow to run the individual commands concurrently: each subprocess.run() call waits for the process to finish that is why it returns CompletedProcess object (notice the word "completed" there). ps1.stdout in your code is a string that is why you have to pass it as input and not the stdin parameter that expects a file/pipe (valid .fileno()).

Either use the shell:

subprocess.run('ls | cowsay', shell=True)

Or use subprocess.Popen, to run the child processes concurrently:

from subprocess import Popen, PIPE

cowsay = Popen('cowsay', stdin=PIPE)
ls = Popen('ls', stdout=cowsay.stdin)
cowsay.communicate()
ls.wait()

See How do I use subprocess.Popen to connect multiple processes by pipes?



来源:https://stackoverflow.com/questions/34147353/python-subprocess-chaining-commands-with-subprocess-run

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!