Python 将 POST 请求卷曲到 pycurl 代码中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31826814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:36:14  来源:igfitidea点击:

Curl POST request into pycurl code

pythonrestpostcurlpycurl

提问by Konrad

I'm trying to convert following curl request into pycurl:

我正在尝试将以下 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

I have following python code:

我有以下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()

Executing this I had an error 415: Unsupported media type, so I have changed:

执行这个我有一个错误 415:不支持的媒体类型,所以我已经改变了:

c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])

into:

进入:

c.setopt(pycurl.HTTPHEADER, [ 'Content-Type: application/json' , 'Accept: application/json'])

This time I have 400: Bad request. But bash code with curl works. Do you have any idea what should I fix in python code?

这次我有 400:错误的请求。但是带有 curl 的 bash 代码有效。你知道我应该在 python 代码中修复什么吗?

采纳答案by Daniel Hepper

In your bash example, the property targetis an array, in your Python example it is a string.

在您的 bash 示例中,该属性target是一个数组,在您的 Python 示例中,它是一个字符串。

Try this:

尝试这个:

data = json.dumps({"name": "abc", "path": "def", "target": ["ghi"]})

I also strongly advise you to check out the requestslibrary which has a much nicer API:

我还强烈建议您查看requests具有更好 API的库:

import requests
data = {"name": "abc", "path": "def", "target": ["ghi"]}
response = requests.post('http://some-url', json=data)
print response.status_code

回答by IJL

It's better simple to use requests library. (http://docs.python-requests.org/en/latest)

使用请求库更简单。( http://docs.python-requests.org/en/latest)

I append python code for your original curl custom headers.

我为您的原始 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())

回答by Brian

I know this is over a year old now, but please try removing the whitespace in your header value.

我知道这已经一年多了,但请尝试删除标题值中的空格。

c.setopt(pycurl.HTTPHEADER, ['Accept:application/json'])

I also prefer using the requests module as well because the APIs/methods are clean and easy to use.

我也更喜欢使用 requests 模块,因为 API/方法干净且易于使用。

回答by Ashwin Venkat

I had similar problem, and I used your code example but updated the httpheadersection as follows:

我遇到了类似的问题,我使用了您的代码示例,但更新了该httpheader部分如下:

c.setopt(pycurl.HTTPHEADER, ['Content-Type:application/json'])

回答by ayush3504

PycURL is a wrapper on the libcurl library written in C language so its Python API can be bit puzzling. As some people are advocating use of python requests instead I just want to point out that it isn't a perfect replacement. For me, its lack of DNS resolution timeout was a deal breaker. I also find it much slower on my Raspberry Pi. This comparison may be relevant: Python Requests vs PyCurl Performance

PycURL 是用 C 语言编写的 libcurl 库的包装器,因此它的 Python API 可能有点令人费解。由于有些人提倡使用 python 请求,我只想指出它不是一个完美的替代品。对我来说,它缺乏 DNS 解析超时是一个交易破坏者。我也发现它在我的 Raspberry Pi 上慢得多。这个比较可能是相关的: Python Requests vs PyCurl Performance

So here's something that doesn't evade OP's question:

所以这里有一些不能回避 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()

There are some more interesting features worth checking out in the libcurl curleasy setopts documentation

libcurl curleasy setopts 文档中有一些更有趣的功能值得查看