不能使用python子进程从curl调用获取返回值

时间:2018-02-27 21:28:55

标签: python curl subprocess rasa-nlu

所以我试图在python中编写一个简单的包装器来调用rasa,这是一个nlu工具。我在命令行上写的命令是:

  

curl -X POST" localhost:5000 / parse" -d' {" q":"我正在寻找他妈的墨西哥食物"}' | python -m json.tool

我期望的输出是这样的:

  

%收到的总百分比%Xferd平均速度时间时间当前时间                                    Dload上载总左转速度   100 545 0 500 100 45 33615 3025 - : - : - - : - : - - : - : - 35714

加上json文件的外印。

我在python中编写了这个程序:

import subprocess

utterance = "Lets say something"


result = subprocess.run(["curl", "-X", "POST", "localhost:5000/parse", "-d", "'{\"q\":\""+utterance+"\"}'", "|", "python", "-m", "json.tool"], stdout=subprocess.PIPE)
print(vars(result))
print(result.stdout.decode('utf-8'))

不幸的是我的输出是这样的,这意味着我实际上并没有从curl调用返回:

  

{' args':[' curl',' -X',' POST',' localhost:5000 /解析',' -d',' \' {" q":"让我们说些什么"} \' ',' |',' python',' -m',' json.tool'],'返回码':2,' stdout':b'',' stderr':无}

如果我从命令行调用我的python程序,这就是输出:

  

curl:选项-m:期望一个合适的数字参数   卷曲:尝试卷曲 - 帮助'或者' curl --manual'欲获得更多信息   {' args':[' curl',' -X',' POST',' localhost:5000 / parse' ;,' -d',' \' {" q":"让我们说些什么"} \'' ;,' |',' python',' -m',' json.tool'],' returncode&#39 ;:2,' stdout':b'',' stderr':无}

我试着到处寻找但是不能让它继续下去。真的很感激一些帮助。

1 个答案:

答案 0 :(得分:1)

更新:我第一次误解了这个问题。匆匆阅读细节,所以我在那里道歉。您遇到问题是因为您尝试使用Popen将两个命令组合在一起。然而,管道运算符是由shell实现的,而不是python。所以它期望你的命令只是一个与curl相关的命令。这很复杂,但你有选择。

我认为对于您的特定示例,最简单的是不要尝试将命令链接到json.tool。你实际上没有必要。你已经在python中了,所以你可以自己打印你自己卷曲的输出。使用python看起来像

import json
import shlex
from subprocess import Popen, PIPE

command = 'curl -XGET http://localhost:9200'

p = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate()

if p.returncode != 0:
    print(err)

j = json.loads(output.decode("utf-8"))
print(json.dumps(j, indent=4, sort_keys=True))

但是,如果你想要的长期实际上是用管道连接多个进程,那么它取决于场景。最简单的方法是将shell=True传递给Popen并传递确切的命令(不是参数列表)。这会将所有内容委托给shell。我需要警告你当命令基于用户输入时,这是非常可利用的。 2.x pipes.quote()3.x shlex.quote()都建议如何转义命令,以便 安全。

from subprocess import Popen, PIPE

command = 'curl -XGET http://localhost:9200 | python -m json.tool'

p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
output, err = p.communicate()

if p.returncode != 0:
    print(err)

print(output.decode("utf-8"))

因此,如果您发现自己需要连接流程但有基于用户输入的内容,则可以使用multiple processes并自行连接。

import shlex
from subprocess import Popen, PIPE

command1 = 'curl -XGET http://localhost:9200'
command2 = 'python -m json.tool'

p1 = Popen(shlex.split(command1), stdout=PIPE)
p2 = Popen(shlex.split(command2), stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()
output, err = p2.communicate()

if p2.returncode != 0:
    print(err)

print(output.decode("utf-8"))
如果你好奇的话,

This问题还有更多关于这个主题的问题。