如何使用Python执行cURL命令?

285

我希望能够在Python中执行一个curl命令。

通常,我只需要在终端中输入命令并按回车键即可。然而,我不知道如何在Python中实现它。

以下是该命令:

curl -d @request.json --header "Content-Type: application/json" https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere

需要发送一个request.json文件以获得响应。

我搜索了很多,感到困惑。我尝试编写了一段代码,虽然我不能完全理解它,也没有成功。

import pycurl
import StringIO

response = StringIO.StringIO()
c = pycurl.Curl()
c.setopt(c.URL, 'https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere')
c.setopt(c.WRITEFUNCTION, response.write)
c.setopt(c.HTTPHEADER, ['Content-Type: application/json','Accept-Charset: UTF-8'])
c.setopt(c.POSTFIELDS, '@request.json')
c.perform()
c.close()
print response.getvalue()
response.close()

错误信息是解析错误。如何正确从服务器获取响应?


1
这个有帮助吗?https://dev59.com/_HE85IYBdhLWcg3wqlaE - br3w5
3
你考虑过使用“Python绑定到cURL”的pycurl吗?根据你的需求,它可能比在后台调用命令行实用程序更有效/方便。 - Sylvain Leroux
3
你需要使用 cURL 吗?你考虑过使用 Requests 吗?如果你刚接触 Python,可能会更简单,因为它往往不太友好。 - vch
我只是想指出这个关于如何在Python中执行shell命令的好答案:https://dev59.com/SnVD5IYBdhLWcg3wGXlI#92395 - tommy.carstensen
11个回答

315

为了简单起见,您应该考虑使用Requests库。

一个带有JSON响应内容的示例可能是这样的:

import requests
r = requests.get('https://github.com/timeline.json')
r.json()

如果您需要更多信息,请查看Quickstart部分,其中有许多实际示例。
针对您的特定curl翻译:
import requests

url = 'https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere'
payload = open("request.json")
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
r = requests.post(url, data=payload, headers=headers)

1
请 @tricknology 尝试寻找这个 Bug,如果您无法找到合适的解决方案,请发布一个新问题。 - otorrillas
4
如果其他人碰巧看到了這個,在我遇到這個問題的原因是我傳遞了一個字符串而不是字典對象作為有效負載。 - tricknology
1
看起来标题中有一个小错别字,应该写成'Accept-Charset': 'UTF-8' - Stephen Lead
1
在发送文件之前打开并解析JSON是不必要的低效操作。你应该先解析JSON,然后使用json.dumps()将其转换回字符串。这是一个糟糕的答案。 - Nathan K
5
“Requests” 是一个额外的依赖项,您需要安装和管理。如果只使用标准库的简单解决方案,请参见 https://dev59.com/VGYr5IYBdhLWcg3wJ2-U#13921930 。 - geekQ
显示剩余3条评论

197

使用curlconverter.com。它将几乎任何curl命令转换为Python、Node.js、PHP、R、Go等。

示例:

curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/asdfasdfasdf

在Python中变成了这样

import requests

json_data = {
    'text': 'Hello, World!',
}

response = requests.post('https://hooks.slack.com/services/asdfasdfasdf', json=json_data)

Curl转换器似乎在处理字段时效果不佳,例如curl -F name=John -F shoesize=11 https://example.com/。它将它们视为文件处理。 - w. Patrick Gale
1
https://curlconverter.com/非常有用! - Benas

38
curl -d @request.json --header "Content-Type: application/json" https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere

其Python实现看起来像这样:

import requests

headers = {
    'Content-Type': 'application/json',
}

params = {
    'key': 'mykeyhere',
}

with open('request.json') as f:
    data = f.read().replace('\n', '')

response = requests.post('https://www.googleapis.com/qpxExpress/v1/trips/search', params=params, headers=headers, data=data)

查看 这个链接,它可以帮助将 cURL 命令转换为 Python、PHP 和 Node.js


29
import requests
url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere"
data = requests.get(url).json

可能吗?

如果您正在尝试发送文件

files = {'request_file': open('request.json', 'rb')}
r = requests.post(url, files=files)
print r.text, print r.json

啊,谢谢 @LukasGraf ,现在我更好地理解了他原来的代码在做什么。

import requests,json
url = "https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere"
my_json_data = json.load(open("request.json"))
req = requests.post(url,data=my_json_data)
print req.text
print 
print req.json # maybe? 

这并不包括来自requests.json文件的数据,并且也没有设置Content-Type: application/json头 - 另外,这将发送一个GET请求,而不是POST - Lukas Graf
1
curl -d @<file>会从<file>中读取要发布的字段,这与文件上传不同。 - Lukas Graf
@LukasGraf 谢谢 :) ... 我很少使用curl(几乎从来不用) - Joran Beasley
2
一个小提示,data = requests.get(url).json 应该是 data = requests.get(url).json() - dpg5000
1
在2014年它是一个属性,现在它是一个函数 :) 不过这个决定很明智。 - Joran Beasley

15

我的回答适用于Python 2.6.2。

import commands

status, output = commands.getstatusoutput("curl -H \"Content-Type:application/json\" -k -u (few other parameters required) -X GET https://example.org -s")

print output

很抱歉未提供所需的参数,因为这是保密的。


如果您需要使用curl的一些特殊选项,例如--resolve,这就是方法。谢谢。 - nikoskip
我怎样才能只获取返回的JSON而不是表格状态? - Grant Gubatan

13

我曾经有过这个问题,因为我必须做一些检索内容的工作,但我只有一个旧版本的Python,并且SSL支持不足。如果你使用的是较旧的MacBook,你就知道我的意思。在任何情况下,curl可以从shell中正常运行(我怀疑它链接了现代SSL支持),因此有时您想要在不使用requestsurllib.request的情况下进行操作。

您可以使用subprocess模块来执行curl并获取检索到的内容:

import subprocess

# 'response' contains a []byte with the retrieved content.
# use '-s' to keep curl quiet while it does its job, but
# it's useful to omit that while you're still writing code
# so you know if curl is working
response = subprocess.check_output(['curl', '-s', baseURL % page_num])

Python 3 的 subprocess 模块还包含具有多个有用选项的 .run() 方法。


我在使用公司MacBook进行代理安全分析时遇到了相同的问题。我将编写一个CURL的包装器来处理一些请求。 - Ângelo Polotto

5

我使用os库。

import os

os.system("sh script.sh")

script.sh字面上只包含curl命令。


2

PYTHON 3

只能在UNIX(Linux / Mac)环境下使用!

使用Python 3执行cURL并解析其JSON数据。

import shlex
import json
import subprocess

# Make sure that cURL has Silent mode (--silent) activated
# otherwise we receive progress data inside err message later
cURL = r"""curl -X --silent POST http://www.test.testtestest/ -d 'username=test'"""

lCmd = shlex.split(cURL) # Splits cURL into an array

p = subprocess.Popen(lCmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate() # Get the output and the err message

json_data = json.loads(out.decode("utf-8"))

print(json_data) # Display now the data

有时,如果您遇到奇怪的错误,也需要在UNIX上安装这些依赖项:
# Dependencies  
sudo apt install libcurl4-openssl-dev libssl-dev
sudo apt install curl

1
使用requests库.. 这段代码是:
curl -LH "Accept: text/x-bibliography; style=apa" https://doi.org/10.5438/0000-0C2G

等于这个:

import requests

headers = {
    'Accept': 'text/x-bibliography; style=apa',
}

r = requests.get('https://doi.org/10.5438/0000-0C2G', headers=headers)


print(r.text)

1
如果你的操作系统支持curl,你可以像这样做:
import os

os.system("curl -d @request.json --header "Content-Type: application/json" https://www.googleapis.com/qpxExpress/v1/trips/search?key=mykeyhere")

我正在使用这种方式... 而且我认为你也可以使用这种方式!

顺便说一下.. 当你安装Python时,模块"os"会自动安装。 所以,你不需要安装包 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接