问题:将subprocess.Popen调用的输出存储在字符串中
我正在尝试在Python中进行系统调用,并将输出存储到我可以在Python程序中操作的字符串中。
#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
我尝试了一些事情,包括此处的一些建议:
检索subprocess.call()的输出
但没有任何运气。
I’m trying to make a system call in Python and store the output to a string that I can manipulate in the Python program.
#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
I’ve tried a few things including some of the suggestions here:
Retrieving the output of subprocess.call()
but without any luck.
回答 0
在Python 2.7或Python 3中
Popen
您可以使用subprocess.check_output()
函数将命令的输出存储在字符串中,而不是直接创建对象:
from subprocess import check_output
out = check_output(["ntpq", "-p"])
在Python 2.4-2.6中
使用communicate
方法。
import subprocess
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE)
out, err = p.communicate()
out
是你想要的。
有关其他答案的重要说明
请注意我如何传递命令。该"ntpq -p"
示例提出了另一回事。由于Popen
不调用外壳程序,因此您将使用命令和选项列表["ntpq", "-p"]
。
In Python 2.7 or Python 3
Instead of making a Popen
object directly, you can use the subprocess.check_output()
function to store output of a command in a string:
from subprocess import check_output
out = check_output(["ntpq", "-p"])
In Python 2.4-2.6
Use the communicate
method.
import subprocess
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE)
out, err = p.communicate()
out
is what you want.
Important note about the other answers
Note how I passed in the command. The "ntpq -p"
example brings up another matter. Since Popen
does not invoke the shell, you would use a list of the command and options—["ntpq", "-p"]
.
回答 1
这为我重定向标准输出工作(stderr可以类似地处理):
from subprocess import Popen, PIPE
pipe = Popen(path, stdout=PIPE)
text = pipe.communicate()[0]
如果对您不起作用,请确切说明您遇到的问题。
This worked for me for redirecting stdout (stderr can be handled similarly):
from subprocess import Popen, PIPE
pipe = Popen(path, stdout=PIPE)
text = pipe.communicate()[0]
If it doesn’t work for you, please specify exactly the problem you’re having.
回答 2
假设这pwd
只是一个示例,可以通过以下方法进行:
import subprocess
p = subprocess.Popen("pwd", stdout=subprocess.PIPE)
result = p.communicate()[0]
print result
看到子文档的另一个例子和更多信息。
Assuming that pwd
is just an example, this is how you can do it:
import subprocess
p = subprocess.Popen("pwd", stdout=subprocess.PIPE)
result = p.communicate()[0]
print result
See the subprocess documentation for another example and more information.
回答 3
subprocess.Popen:http : //docs.python.org/2/library/subprocess.html#subprocess.Popen
import subprocess
command = "ntpq -p" # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True)
#Launch the shell command:
output = process.communicate()
print output[0]
在Popen构造函数中,如果shell为True,则应以字符串而不是序列的形式传递命令。否则,只需将命令拆分为一个列表:
command = ["ntpq", "-p"] # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None)
如果您还需要将标准错误读取到Popen初始化中,则可以将stderr设置为subprocess.PIPE或subprocess.STDOUT:
import subprocess
command = "ntpq -p" # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
#Launch the shell command:
output, error = process.communicate()
subprocess.Popen: http://docs.python.org/2/library/subprocess.html#subprocess.Popen
import subprocess
command = "ntpq -p" # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True)
#Launch the shell command:
output = process.communicate()
print output[0]
In the Popen constructor, if shell is True, you should pass the command as a string rather than as a sequence. Otherwise, just split the command into a list:
command = ["ntpq", "-p"] # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None)
If you need to read also the standard error, into the Popen initialization, you can set stderr to subprocess.PIPE or to subprocess.STDOUT:
import subprocess
command = "ntpq -p" # the shell command
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
#Launch the shell command:
output, error = process.communicate()
回答 4
对于Python 2.7+,惯用的答案是使用 subprocess.check_output()
您还应该在调用子流程时注意对参数的处理,因为这可能会造成一些混乱。
如果args只是单个命令而没有自己的args(或您已shell=True
设置),则它可以是字符串。否则,它必须是一个列表。
例如…调用ls
命令,这很好:
from subprocess import check_call
check_call('ls')
是这样的:
from subprocess import check_call
check_call(['ls',])
但是,如果要将一些args传递给shell命令,则不能这样做:
from subprocess import check_call
check_call('ls -al')
相反,您必须将其作为列表传递:
from subprocess import check_call
check_call(['ls', '-al'])
该shlex.split()
函数有时在创建子进程之前将字符串拆分成类似shell的语法很有用…就像这样:
from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))
for Python 2.7+ the idiomatic answer is to use subprocess.check_output()
You should also note the handling of arguments when invoking a subprocess, as it can be a little confusing….
If args is just single command with no args of its own (or you have shell=True
set), it can be a string. Otherwise it must be a list.
for example… to invoke the ls
command, this is fine:
from subprocess import check_call
check_call('ls')
so is this:
from subprocess import check_call
check_call(['ls',])
however, if you want to pass some args to the shell command, you can’t do this:
from subprocess import check_call
check_call('ls -al')
instead, you must pass it as a list:
from subprocess import check_call
check_call(['ls', '-al'])
the shlex.split()
function can sometimes be useful to split a string into shell-like syntax before creating a subprocesses…
like this:
from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))
回答 5
这完全适合我:
import subprocess
try:
#prints results and merges stdout and std
result = subprocess.check_output("echo %USERNAME%", stderr=subprocess.STDOUT, shell=True)
print result
#causes error and merges stdout and stderr
result = subprocess.check_output("copy testfds", stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError, ex: # error code <> 0
print "--------error------"
print ex.cmd
print ex.message
print ex.returncode
print ex.output # contains stdout and stderr together
This works perfectly for me:
import subprocess
try:
#prints results and merges stdout and std
result = subprocess.check_output("echo %USERNAME%", stderr=subprocess.STDOUT, shell=True)
print result
#causes error and merges stdout and stderr
result = subprocess.check_output("copy testfds", stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError, ex: # error code <> 0
print "--------error------"
print ex.cmd
print ex.message
print ex.returncode
print ex.output # contains stdout and stderr together
回答 6
这对我来说是完美的。您将在元组中获得返回码,stdout和stderr。
from subprocess import Popen, PIPE
def console(cmd):
p = Popen(cmd, shell=True, stdout=PIPE)
out, err = p.communicate()
return (p.returncode, out, err)
例如:
result = console('ls -l')
print 'returncode: %s' % result[0]
print 'output: %s' % result[1]
print 'error: %s' % result[2]
This was perfect for me.
You will get the return code, stdout and stderr in a tuple.
from subprocess import Popen, PIPE
def console(cmd):
p = Popen(cmd, shell=True, stdout=PIPE)
out, err = p.communicate()
return (p.returncode, out, err)
For Example:
result = console('ls -l')
print 'returncode: %s' % result[0]
print 'output: %s' % result[1]
print 'error: %s' % result[2]
回答 7
接受的答案仍然是好的,只是对新功能的一些评论。从python 3.6开始,您可以直接在中处理编码check_output
,请参阅文档。现在返回一个字符串对象:
import subprocess
out = subprocess.check_output(["ls", "-l"], encoding="utf-8")
在python 3.7中,capture_output
向subprocess.run()添加了一个参数,该参数为我们执行了一些Popen / PIPE处理,请参见python docs:
import subprocess
p2 = subprocess.run(["ls", "-l"], capture_output=True, encoding="utf-8")
p2.stdout
The accepted answer is still good, just a few remarks on newer features. Since python 3.6, you can handle encoding directly in check_output
, see documentation. This returns a string object now:
import subprocess
out = subprocess.check_output(["ls", "-l"], encoding="utf-8")
In python 3.7, a parameter capture_output
was added to subprocess.run(), which does some of the Popen/PIPE handling for us, see the python docs :
import subprocess
p2 = subprocess.run(["ls", "-l"], capture_output=True, encoding="utf-8")
p2.stdout
回答 8
import os
list = os.popen('pwd').read()
在这种情况下,列表中将只有一个元素。
import os
list = os.popen('pwd').read()
In this case you will only have one element in the list.
回答 9
我根据此处的其他答案编写了一个小函数:
def pexec(*args):
return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip()
用法:
changeset = pexec('hg','id','--id')
branch = pexec('hg','id','--branch')
revnum = pexec('hg','id','--num')
print('%s : %s (%s)' % (revnum, changeset, branch))
I wrote a little function based on the other answers here:
def pexec(*args):
return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip()
Usage:
changeset = pexec('hg','id','--id')
branch = pexec('hg','id','--branch')
revnum = pexec('hg','id','--num')
print('%s : %s (%s)' % (revnum, changeset, branch))
回答 10
在Python 3.7中,capture_output
为引入了新的关键字参数subprocess.run
。启用简短的说明:
import subprocess
p = subprocess.run("echo 'hello world!'", capture_output=True, shell=True, encoding="utf8")
assert p.stdout == 'hello world!\n'
In Python 3.7 a new keyword argument capture_output
was introduced for subprocess.run
. Enabling the short and simple:
import subprocess
p = subprocess.run("echo 'hello world!'", capture_output=True, shell=True, encoding="utf8")
assert p.stdout == 'hello world!\n'
回答 11
import subprocess
output = str(subprocess.Popen("ntpq -p",shell = True,stdout = subprocess.PIPE,
stderr = subprocess.STDOUT).communicate()[0])
这是一线解决方案
import subprocess
output = str(subprocess.Popen("ntpq -p",shell = True,stdout = subprocess.PIPE,
stderr = subprocess.STDOUT).communicate()[0])
This is one line solution
回答 12
以下内容在单个变量中捕获了进程的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)
The following captures stdout and stderr of the process in a single variable. It is Python 2 and 3 compatible:
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
If your command is a string rather than an array, prefix this with:
import shlex
command = shlex.split(command)
回答 13
对于python 3.5,我根据先前的答案提出了功能。日志可能会被删除,以为拥有它很高兴
import shlex
from subprocess import check_output, CalledProcessError, STDOUT
def cmdline(command):
log("cmdline:{}".format(command))
cmdArr = shlex.split(command)
try:
output = check_output(cmdArr, stderr=STDOUT).decode()
log("Success:{}".format(output))
except (CalledProcessError) as e:
output = e.output.decode()
log("Fail:{}".format(output))
except (Exception) as e:
output = str(e);
log("Fail:{}".format(e))
return str(output)
def log(msg):
msg = str(msg)
d_date = datetime.datetime.now()
now = str(d_date.strftime("%Y-%m-%d %H:%M:%S"))
print(now + " " + msg)
if ("LOG_FILE" in globals()):
with open(LOG_FILE, "a") as myfile:
myfile.write(now + " " + msg + "\n")
For python 3.5 I put up function based on previous answer. Log may be removed, thought it’s nice to have
import shlex
from subprocess import check_output, CalledProcessError, STDOUT
def cmdline(command):
log("cmdline:{}".format(command))
cmdArr = shlex.split(command)
try:
output = check_output(cmdArr, stderr=STDOUT).decode()
log("Success:{}".format(output))
except (CalledProcessError) as e:
output = e.output.decode()
log("Fail:{}".format(output))
except (Exception) as e:
output = str(e);
log("Fail:{}".format(e))
return str(output)
def log(msg):
msg = str(msg)
d_date = datetime.datetime.now()
now = str(d_date.strftime("%Y-%m-%d %H:%M:%S"))
print(now + " " + msg)
if ("LOG_FILE" in globals()):
with open(LOG_FILE, "a") as myfile:
myfile.write(now + " " + msg + "\n")
回答 14
使用ckeck_output
方法subprocess
import subprocess
address = 192.168.x.x
res = subprocess.check_output(['ping', address, '-c', '3'])
最后解析字符串
for line in res.splitlines():
希望对您有所帮助,编码愉快
Use ckeck_output
method of subprocess
import subprocess
address = 192.168.x.x
res = subprocess.check_output(['ping', address, '-c', '3'])
Finally parse the string
for line in res.splitlines():
Hope it helps, happy coding