有没有办法在python中执行HTTP PUT


220

我需要使用PUTpython中的HTTP将一些数据上传到服务器。从我对urllib2文档的简短阅读中,它只能使用HTTP POST。有什么办法可以PUT在python中执行HTTP 吗?

Answers:


311

过去,我使用过各种python HTTP库,而我最喜欢的是“ Requests ”。现有的库具有相当有用的接口,但是对于简单的操作,代码最终可能会花几行时间。请求中的基本PUT如下所示:

payload = {'username': 'bob', 'email': 'bob@bob.com'}
>>> r = requests.put("http://somedomain.org/endpoint", data=payload)

然后,您可以使用以下方法检查响应状态代码:

r.status_code

或回应:

r.content

请求有很多语法和快捷方式,可以使您的生活更轻松。


11
即使上面的代码看起来非常简单,也不要以任何方式推断出“请求”缺乏或功能不足。界面高度整洁,功能强大。
乔纳森·哈特利

5
我不知道这个答案要花多长时间才能逐渐累积票数,直到它成为投票最高的新答案?
乔纳森·哈特利

2
你不知道这有多棒!!!我在挣扎着一个简陋的Java库!...我想我有点爱您指向“请求”!
Shehaaz 2013年

3
json=payload如果您希望数据在正文中,请使用参数。
ManuelSchneid3r

1
我想快速指出,该接口比其他答案要好,因为它是函数式编程。当一个具有简单数据结构作为参数的函数执行操作时,为什么要创建一个对象。我希望其他python库也能效仿。
马克

242
import urllib2
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request('http://example.org', data='your_put_data')
request.add_header('Content-Type', 'your/contenttype')
request.get_method = lambda: 'PUT'
url = opener.open(request)

4
看起来有点肮脏,但是它运行得很完美
Rory

6
如果您要继承urllib2.Request而不是对其进行猴子修补,那么它就不那么骇人听闻了。
詹森·库姆斯

23
撰写本文时,这个答案非常出色,但是如今,使用“ requests”包要容易得多,请参阅John Carter的答案。“要求”绝不是玩具-它非常有能力。
乔纳森·哈特利

5
这个答案是规范的,但是已经过时了。请考虑改用requests库。
jsalonen 2012年

13
谢谢,我不想使用标准python库之外的任何东西,而且效果很好。我不太明白为什么urllib2设计为仅满足GET和POST的标准要求,但是这种解决方法是冠军。可以在多个调用中重用urllib2.build_opener(urllib2.HTTPHandler)吗?
WeNeedAnswers 2012年

46

Httplib似乎是一个更清洁的选择。

import httplib
connection =  httplib.HTTPConnection('1.2.3.4:1234')
body_content = 'BODY CONTENT GOES HERE'
connection.request('PUT', '/url/path/to/put/to', body_content)
result = connection.getresponse()
# Now result.status and result.reason contains interesting stuff

如果您(或您的任何潜在用户)需要代理支持,请不要使用httplib。有关详细信息,请参见本文
詹森·库姆斯

你怎么会那么说?您的文章明确指出了它的工作原理。参见Rolf Wester的回答,他说urllib失败,但是httplib有效。
2011年

仅当用户明确连接到代理并修改请求以在GET参数中包含完整URL时,httplib才起作用。urllib失败的原因是因为未正确设置http_proxy。urllib的使用httplib的场景下,也处理重定向,代理等
贾森R.库姆斯

尽管此解决方案可行,但使用请求的解决方案更简单,更优雅,我认为更好。
tgrosinger 2012年

1
@tgrosinger我同意。在存在请求之前,已发布此答案。到目前为止,唯一可以使用此解决方案的情况是仅提供Python标准库。否则,我也建议您使用请求。
2012年

8

您应该看看httplib模块。它应该让您发出所需的任何HTTP请求。


不错的解决方案,安静的pythonic,但距离金属太近,并且已经涉及编写许多其他代码
Rory

8

我有一阵子需要解决此问题,以便可以充当RESTful API的客户端。我选择了httplib2,因为它允许我除了GET和POST之外还发送PUT和DELETE。Httplib2不是标准库的一部分,但是您可以从奶酪店轻松获得它。


2
httplib2是边缘放弃软件。尽管社区做出了贡献(补丁),但仍有许多无法修复的错误。我建议在任何生产环境中使用httplib2之前都要三思。
詹森·库姆斯

8

您可以使用请求库,与采用urllib2方法相比,它可以简化很多事情。首先从pip安装它:

pip install requests

有关安装请求的更多信息。

然后设置放置请求:

import requests
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}

# Create your header as required
headers = {"content-type": "application/json", "Authorization": "<auth-key>" }

r = requests.put(url, data=json.dumps(payload), headers=headers)

请参阅请求库快速入门。我认为这比urllib2简单得多,但确实需要安装和导入此附加软件包。


请求是否也支持PUT?
杰夫2014年

请求支持获取,放置,发布,删除标题和选项。修复了使用put的示例。查看请求快速入门。
radtek

@RPradeep谢谢你。
radtek '16

8

这在python3中变得更好,并在stdlib文档中进行了记录

urllib.request.Request班获得了method=...在python3参数。

一些示例用法:

req = urllib.request.Request('https://example.com/', data=b'DATA!', method='PUT')
urllib.request.urlopen(req)


3

您看过put.py吗?我过去曾经用过。您也可以使用urllib修改自己的请求。


我真的不想使用一些随机的人http库
Rory

尝试导入put放入#pip install put进行下载/解压put找不到符合要求的下载内容put清理...根本找不到分发的内容
Ashish Karpe

#tail -f /root/.pip/pip.log追溯(最近一次调用为最后):文件“ /usr/lib/python2.7/dist-packages/pip/basecommand.py”,第122行,处于主要状态= self.run(options,args)文件“ /usr/lib/python2.7/dist-packages/pip/commands/install.py”,行278,在运行require_set.prepare_files(finder,force_root_egg_info = self.bundle,捆绑包)中= self.bundle)在prepare_files中的文件“ /usr/lib/python2.7/dist-packages/pip/req.py”,行1178
Ashish Karpe

url = finder.find_requirement(req_to_install,upgrade = self.upgrade)文件“ /usr/lib/python2.7/dist-packages/pip/index.py”,第277行,在find_requirement中引发DistributionNotFound('找不到所有分布for%s'%req)DistributionNotFound:完全未分配看跌期权
Ashish Karpe

2

当然,您可以使用现有的标准库在任何级别(从套接字到调整urllib)进行滚动。

http://pycurl.sourceforge.net/

“ PyCurl是libcurl的Python接口。”

“ libcurl是一个免费且易于使用的客户端URL传输库,...支持... HTTP PUT”

“ PycURL的主要缺点是它是libcurl上相对较薄的一层,没有任何不错的Pythonic类层次结构。这意味着除非您已经熟悉libcurl的C API,否则它的学习曲线就比较陡峭。”


我敢肯定它会起作用,但是我想要更多的pythonic
Rory

2

如果要保留在标准库中,则可以子类化urllib2.Request

import urllib2

class RequestWithMethod(urllib2.Request):
    def __init__(self, *args, **kwargs):
        self._method = kwargs.pop('method', None)
        urllib2.Request.__init__(self, *args, **kwargs)

    def get_method(self):
        return self._method if self._method else super(RequestWithMethod, self).get_method()


def put_request(url, data):
    opener = urllib2.build_opener(urllib2.HTTPHandler)
    request = RequestWithMethod(url, method='PUT', data=data)
    return opener.open(request)

0

一个更合适的方法requests是:

import requests

payload = {'username': 'bob', 'email': 'bob@bob.com'}

try:
    response = requests.put(url="http://somedomain.org/endpoint", data=payload)
    response.raise_for_status()
except requests.exceptions.RequestException as e:
    print(e)
    raise

如果HTTP PUT请求中存在错误,则会引发异常。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.