我正在尝试将以下curl请求转换为pycurl:
curl -v
-H Accept:application/json \
-H Content-Type:application/json \
-d "{
name: 'abc',
path: 'def',
target: [ 'ghi' ]
}" \
-X POST http://some-url
我有以下python代码:
import pycurl, json
c = pycurl.Curl()
c.setopt(pycurl.URL, 'http://some-url')
c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])
data = json.dumps({"name": "abc", "path": "def", "target": "ghi"})
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, data)
c.setopt(pycurl.VERBOSE, 1)
c.perform()
print curl_agent.getinfo(pycurl.RESPONSE_CODE)
c.close()
执行此操作时出现错误415:不支持的媒体类型,所以我更改了:
c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])
成:
c.setopt(pycurl.HTTPHEADER, [ 'Content-Type: application/json' , 'Accept: application/json'])
这次我有400:请求不好。但是使用curl的bash代码可行。你知道我应该在python代码中修复什么吗?
答案 0 :(得分:2)
在bash示例中,属性target
是一个数组,在Python示例中它是一个字符串。
试试这个:
data = json.dumps({"name": "abc", "path": "def", "target": ["ghi"]})
我还强烈建议您查看具有更好API的requests
库:
import requests
data = {"name": "abc", "path": "def", "target": ["ghi"]}
response = requests.post('http://some-url', json=data)
print response.status_code
答案 1 :(得分:2)
我知道现在已超过一年了,但请尝试删除标头值中的空白。
c.setopt(pycurl.HTTPHEADER, ['Accept:application/json'])
我也更喜欢使用请求模块,因为API /方法干净且易于使用。
答案 2 :(得分:1)
PycURL是用C语言编写的libcurl库的包装,因此其Python API可能让人有些困惑。正如某些人提倡使用python请求一样,我只想指出这不是一个完美的替代方法。对我而言,其缺乏DNS解析超时功能会破坏交易。我也发现Raspberry Pi的速度慢得多。这种比较可能是相关的: Python Requests vs PyCurl Performance
因此,有些事情无法回避OP的问题:
import pycurl
import json
from cStringIO import StringIO
curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://some-url')
curl.setopt(pycurl.HTTPHEADER, ['Accept: application/json',
'Content-Type: application/json'])
curl.setopt(pycurl.POST, 1)
# If you want to set a total timeout, say, 3 seconds
curl.setopt(pycurl.TIMEOUT_MS, 3000)
## depending on whether you want to print details on stdout, uncomment either
# curl.setopt(pycurl.VERBOSE, 1) # to print entire request flow
## or
# curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean
# preparing body the way pycurl.READDATA wants it
# NOTE: you may reuse curl object setup at this point
# if sending POST repeatedly to the url. It will reuse
# the connection.
body_as_dict = {"name": "abc", "path": "def", "target": "ghi"}
body_as_json_string = json.dumps(body_as_dict) # dict to json
body_as_file_object = StringIO(body_as_json_string)
# prepare and send. See also: pycurl.READFUNCTION to pass function instead
curl.setopt(pycurl.READDATA, body_as_file_object)
curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string))
curl.perform()
# you may want to check HTTP response code, e.g.
status_code = curl.getinfo(pycurl.RESPONSE_CODE)
if status_code != 200:
print "Aww Snap :( Server returned HTTP status code {}".format(status_code)
# don't forget to release connection when finished
curl.close()
还有一些更有趣的功能值得在libcurl curleasy setopts documentation中查看
答案 3 :(得分:0)
我有类似的问题,我使用了您的代码示例,但对httpheader
部分进行了如下更新:
c.setopt(pycurl.HTTPHEADER, ['Content-Type:application/json'])
答案 4 :(得分:-5)
使用请求库更简单。 (http://docs.python-requests.org/en/latest)
我为原始curl自定义标题添加了python代码。
import json
import requests
url = 'http://some-url'
headers = {'Content-Type': "application/json; charset=xxxe", 'Accept': "application/json"}
data = {"name": "abc", "path": "def", "target": ["ghi"]}
res = requests.post(url, json=data, headers=headers)
print (res.status_code)
print (res.raise_for_status())