我正在尝试在Python中进行系统调用,并将输出存储到我可以在Python程序中操作的字符串中。
#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
我尝试了一些事情,包括此处的一些建议:
但没有任何运气。
我正在尝试在Python中进行系统调用,并将输出存储到我可以在Python程序中操作的字符串中。
#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
我尝试了一些事情,包括此处的一些建议:
但没有任何运气。
Answers:
在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"]
。
Popen.communicate
直到进程终止才返回。
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
subprocess.check_output()
返回一个bytes
对象,而不是str
。如果您只想打印结果,那将没有任何区别。但是,如果您想对结果使用诸如此类的方法myString.split("\n")
,则必须首先对bytes
对象subprocess.check_output(myParams).decode("utf-8")
进行解码:例如。
universal_newlines=True
为参数可以帮助我在Python 3中获取字符串对象。如果universal_newlines为True,它们将以默认编码的文本模式打开。否则,它们将作为二进制流打开。
这为我重定向标准输出工作(stderr可以类似地处理):
from subprocess import Popen, PIPE
pipe = Popen(path, stdout=PIPE)
text = pipe.communicate()[0]
如果对您不起作用,请确切说明您遇到的问题。
\n
。
pipe.returncode == 0
在最后一行之后进行检查。
Popen
返回了stdout
和的元组stderr
,因此当您访问时,[0]
您只是在抓取stdout
。您也可以做text, err = pipe.communicate()
,然后text
得到您所期望的
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()
对于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'))
这完全适合我:
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
这对我来说是完美的。您将在元组中获得返回码,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]
接受的答案仍然是好的,只是对新功能的一些评论。从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
import os
list = os.popen('pwd').read()
在这种情况下,列表中将只有一个元素。
os.popen
不推荐使用该subprocess
模块。
import subprocess
output = str(subprocess.Popen("ntpq -p",shell = True,stdout = subprocess.PIPE,
stderr = subprocess.STDOUT).communicate()[0])
这是一线解决方案
以下内容在单个变量中捕获了进程的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)
对于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")
使用ckeck_output
方法subprocess
import subprocess
address = 192.168.x.x
res = subprocess.check_output(['ping', address, '-c', '3'])
最后解析字符串
for line in res.splitlines():
希望对您有所帮助,编码愉快
"ntpq -p"
,这是该文件的另一部分。问题超出您的要求。