Python 以字符串形式存储subprocess.Popen调用的输出

Python 以字符串形式存储subprocess.Popen调用的输出,python,subprocess,Python,Subprocess,我正在尝试用Python进行系统调用,并将输出存储到可以在Python程序中操作的字符串中 #!/usr/bin/python import subprocess p2 = subprocess.Popen("ntpq -p") 我尝试了一些方法,包括这里的一些建议: 但是没有任何运气。这对我重定向stdout很有效(stderr可以类似地处理): 如果对您不起作用,请确切说明您遇到的问题。假设pwd只是一个示例,您可以这样做: import subprocess p = subproce

我正在尝试用Python进行系统调用,并将输出存储到可以在Python程序中操作的字符串中

#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
我尝试了一些方法,包括这里的一些建议:


但是没有任何运气。

这对我重定向stdout很有效(stderr可以类似地处理):


如果对您不起作用,请确切说明您遇到的问题。

假设
pwd
只是一个示例,您可以这样做:

import subprocess

p = subprocess.Popen("pwd", stdout=subprocess.PIPE)
result = p.communicate()[0]
print result

有关详细信息,请参阅。Python2.7或Python3中的

您可以使用以字符串形式存储命令的输出,而不是直接创建
Popen
对象:

from subprocess import check_output
out = check_output(["ntpq", "-p"])
在Python 2.4-2.6中

使用
通信
方法

import subprocess
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE)
out, err = p.communicate()
out
是您想要的

关于其他答案的重要注意事项

注意我是如何传入命令的。
“ntpq-p”
示例提出了另一个问题。由于
Popen
不调用shell,因此可以使用命令和选项的列表-
[“ntpq”,“-p”]


在这种情况下,列表中只有一个元素。

Python 2

在Popen构造函数中,如果shell为True,则应将命令作为字符串而不是序列传递。否则,只需将命令拆分为一个列表:

command = ["ntpq", "-p"]
process = Popen(command, stdout=PIPE, stderr=None)
如果还需要将标准错误读入Popen初始化,则应将stderr设置为PIPE或STDOUT:

Python 3


我在这里根据其他答案编写了一个小函数:

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))

这对我来说非常有效:

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 
导入子流程
尝试:
#打印结果并合并标准输出和标准输出
结果=子进程。检查输出(“echo%USERNAME%”,stderr=subprocess.STDOUT,shell=True)
打印结果
#导致错误并合并stdout和stderr
结果=子进程。检查输出(“复制testfds”,stderr=子进程。STDOUT,shell=True)
除了subprocess.CalledProcessError之外,例如:#错误代码0
打印“----------错误------”
打印ex.cmd
打印邮件
打印退货代码
打印输出#同时包含标准输出和标准输出
这对我来说太完美了。 您将在元组中获得返回代码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 2.7+来说,惯用的答案是使用

您还应该注意调用子流程时参数的处理,因为它可能会有点混乱

如果args只是一个没有自己的args的命令(或者您设置了
shell=True
set),那么它可以是一个字符串。否则它必须是一个列表

例如。。。要调用
ls
命令,可以执行以下操作:

from subprocess import check_call
check_call('ls')
这就是:

from subprocess import check_call
check_call(['ls',])
但是,如果要将一些参数传递给shell命令,则不能执行以下操作:

相反,您必须将其作为列表传递:

from subprocess import check_call
check_call(['ls', '-al'])
在创建子流程之前,该函数有时可以用于将字符串拆分为类似shell的语法。。。 像这样:

from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))

下面在单个变量中捕获流程的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.6以来,您可以在
检查输出中直接处理编码,请参阅。现在返回一个字符串对象:

import subprocess 
out = subprocess.check_output(["ls", "-l"], encoding="utf-8")
在python 3.7中,一个参数
capture\u output
被添加到subprocess.run(),它为我们执行一些Popen/PIPE处理,请参见:


对于Python3.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")

在Python 3.7中,您可以使用新的
capture\u output=
关键字参数:

导入子流程
p=subprocess.run([“echo”,“hello world!”],capture\u output=True,text=True)
断言p.stdout=='你好,世界\不

使用
检查
子流程
模块的输出方法

import subprocess

address = '192.168.x.x'
res = subprocess.check_output(['ping', address, '-c', '3'])
最后解析字符串

for line in res.splitlines():

希望它能有所帮助,happy coding

操作系统。popen
被弃用,取而代之的是
子流程
模块。这对使用2.2.X系列Python的旧盒子上的管理员来说非常有帮助。发布您运行的实际代码以及实际的回溯或意外的行为对于这样的具体问题总是很好的。例如,我不知道您试图做些什么来获取输出,我怀疑您实际上没有做到这一点,您可能会遇到一个错误,即没有找到
“ntpq-p”
的文件,这与您所问的问题不同。在这种情况下,python是否会等待此系统调用完成?或者需要显式调用wait/waitpid函数吗?@NoneType,
Popen.communicate
在进程终止之前不会返回。如果要获取错误流,请添加stderr:
p=subprocess.Popen([“ntpq”,“-p”],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
小心,
subprocess.check\u output()
返回一个
bytes
对象,而不是
str
。如果你只想打印结果,那没什么区别。但是,如果您想在结果中使用诸如
myString.split(“\n”)
之类的方法,则必须首先解码
bytes
对象:
subprocess。例如,检查输出(myParams)。解码(“utf-8”)
。添加
universal\u newlines=True
作为参数有助于我在Python 3中获取字符串对象。如果universal_新行为True,则它们将以文本模式以默认编码打开。五年后,这个问题仍然受到很多人的喜爱。谢谢你的2.7+更新,Corey!这确实产生了一些奇怪的物体。当我将其转换为字符串时,它会像
\n
一样转义空白。请注意,这不会检查子进程是否运行
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)
import subprocess
output = str(subprocess.Popen("ntpq -p",shell = True,stdout = subprocess.PIPE, 
stderr = subprocess.STDOUT).communicate()[0])
import subprocess 
out = subprocess.check_output(["ls", "-l"], encoding="utf-8")
import subprocess 
p2 = subprocess.run(["ls", "-l"], capture_output=True, encoding="utf-8")
p2.stdout
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")
import subprocess

address = '192.168.x.x'
res = subprocess.check_output(['ping', address, '-c', '3'])
for line in res.splitlines():