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

问题描述 投票:1回答:1

所以我试图在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 / parse',' - d','\'{“q”:“让我们说些什么”} \'', '|','python',' - m','json.tool'],'returncode':2,'stdout':b'','stderr':无}

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

curl:选项-m:期望一个正确的数值参数curl:尝试'curl --help'或'curl --manual'获取更多信息{'args':['curl',' - X','POST',' localhost:5000 / parse',' - d','\'{“q”:“让我们说些什么”} \'','|','python',' - m','json.tool'], 'returncode':2,'stdout':b'','stderr':无}

我试着到处寻找但是不能让它继续下去。非常感谢一些帮助。

python curl subprocess rasa-nlu
1个回答
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问题还有很多关于这个主题的问题。

© www.soinside.com 2019 - 2024. All rights reserved.