无法使用python子进程从curl调用获取返回值
因此,我试图用python编写一个简单的包装器来调用rasa,这是一个来自的nlu工具。我将在命令行上编写的命令如下: curl-X POST“localhost:5000/parse”-d'{“q”:“我在找他妈的墨西哥食物”}| python-mjson.tool 我期望的输出如下: %总接收百分比%x平均速度时间电流 数据加载上载总左速度 1005450500100453361503025025025025——:::::::::::::--35714 加上json文件的输出 我用python编写了这个程序:无法使用python子进程从curl调用获取返回值,python,curl,subprocess,rasa-nlu,Python,Curl,Subprocess,Rasa Nlu,因此,我试图用python编写一个简单的包装器来调用rasa,这是一个来自的nlu工具。我将在命令行上编写的命令如下: curl-X POST“localhost:5000/parse”-d'{“q”:“我在找他妈的墨西哥食物”}| python-mjson.tool 我期望的输出如下: %总接收百分比%x平均速度时间电流 数据加载上载总左速度 1005450500100453361503025025025025——:::::::::::::--35714 加上json文件的输出 我用pytho
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':None}
如果我从命令行调用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':None}
我试着到处找,但就是找不到。非常感谢您的帮助。更新:我第一次误解了这个问题。匆忙阅读了细节,所以我向你道歉。您遇到了一个问题,因为您正试图使用Popen将两个命令管道连接在一起。然而,管道操作符是由shell实现的,而不是python。所以它期望您的命令只是一个与curl相关的命令。这很复杂,但你有选择 我认为对于您的特定示例,最简单的方法是不要尝试将命令链接到json.tool。你其实不需要它。您已经使用python了,所以您可以直接打印从curl获得的输出。使用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。我需要警告您,当命令基于用户输入时,这是非常容易被利用的。pipes.quote()
和shlex.quote()
都建议如何转义该命令,以确保其安全
因此,如果您发现自己需要连接进程,但有基于用户输入的东西,您可以自己使用并连接它们
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"))
如果您好奇的话,这个问题还有很多相关内容。我尝试过使用Popen,不幸的是,您使用我的命令生成的确切代码产生了以下结果:b“curl:option-m:需要一个合适的数值参数\ncurl:请尝试“curl--help”或“curl--manual”以了解更多信息\n“b”我稍后再试,但是您可能可以删除
|python-mjson.tool
部分。您已经使用python,因此如果需要,您可以在代码中很好地打印出来。@JulianKurz更新了答案。我完全没有仔细阅读你的问题。SteveJ关于pycurl的话看起来也很有趣,因为它是在不调用外部进程的情况下执行curl的一个更好的替代方案。非常感谢你,只是为了了解一些东西,我尝试了你的两种选择,它们都工作得很好。所以我当然实现了第一个。虽然我可能会玩弄第二个选项,试图造成伤害,但由于用户输入是基于语音的,我发现很有趣,看看它是否仍然可行。@JulianKurz我又做了一次更新。2.x和3.x都建议转义我在使用shell=True
时提到的命令。我没有立即让它工作,所以我稍后会尝试,并更新示例,但可能值得一试。将文本转换为语音转换为代码可能很困难,但仍然是可能的。如果这有助于接受答案,那将非常有帮助。一个想法,你看过pycurl或请求了吗?你将编写本机代码,更容易实现,更容易阅读,更容易调试。
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"))