Có cách nào để thực hiện HTTP PUT trong python không


220

Tôi cần tải một số dữ liệu lên máy chủ bằng HTTP PUTtrong python. Từ việc đọc tóm tắt các tài liệu urllib2 của tôi, nó chỉ thực hiện HTTP POST. Có cách nào để làm HTTP PUTtrong python không?

Câu trả lời:


311

Trước đây, tôi đã sử dụng nhiều loại lib HTTP python và tôi đã giải quyết ' Yêu cầu ' là sở thích của mình. Các lib hiện tại có các giao diện khá hữu dụng, nhưng mã cuối cùng có thể là một vài dòng quá dài cho các hoạt động đơn giản. Một PUT cơ bản trong các yêu cầu trông giống như:

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

Sau đó, bạn có thể kiểm tra mã trạng thái phản hồi bằng:

r.status_code

hoặc phản hồi với:

r.content

Yêu cầu có nhiều đường và lối tắt đồng bộ sẽ giúp cuộc sống của bạn dễ dàng hơn.


11
Mặc dù đoạn mã trên trông cực kỳ đơn giản, nhưng đừng suy luận rằng 'yêu cầu' là trong bất kỳ cách nào thiếu hoặc không được cung cấp năng lượng. Nó cực kỳ có khả năng, chỉ với một giao diện rất gọn gàng.
Jonathan Hartley

5
Tôi tự hỏi sẽ mất bao lâu để câu trả lời này tích lũy dần dần cho đến khi nó trở thành câu trả lời được bình chọn cao nhất?
Jonathan Hartley

2
Bạn không hiểu bao nhiêu điều này là tuyệt vời !!! Tôi đã vật lộn với một thư viện java nhàu nát! ... Tôi nghĩ rằng tôi yêu bạn vì đã chỉ vào "Yêu cầu"!
Shehaaz

3
Sử dụng json=payloadtham số nếu bạn muốn dữ liệu nằm trong cơ thể.
ManuelSchneid3r

1
Tôi muốn nhanh chóng chỉ ra rằng giao diện này tốt hơn câu trả lời khác, bởi vì đó là lập trình chức năng. Tại sao tạo một đối tượng khi một hàm có cấu trúc dữ liệu đơn giản như các tham số sẽ làm. Tôi muốn các thư viện python khác sẽ làm theo.
Marc

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
Trông giống như một chút hack bẩn, nhưng nó dường như hoạt động thanh lịch và đầy đủ
Rory

6
Sẽ ít bị hack hơn nếu bạn phân lớp urllib2.Request thay vì khỉ vá nó.
Jason R. Coombs

23
Câu trả lời này thật tuyệt vời khi được viết, nhưng ngày nay việc sử dụng gói 'yêu cầu' dễ dàng hơn rất nhiều, hãy xem câu trả lời của John Carter. 'Yêu cầu' hoàn toàn không phải là một món đồ chơi - nó cực kỳ có khả năng.
Jonathan Hartley

5
Câu trả lời này là kinh điển, nhưng lỗi thời. Xin vui lòng, xem xét sử dụng requeststhư viện thay thế.
jsalonen

13
Cảm ơn bạn, tôi không muốn sử dụng bất cứ thứ gì bên ngoài thư viện python tiêu chuẩn và điều này hoạt động hoàn hảo. Tôi hoàn toàn không hiểu tại sao urllib2 được thiết kế để chỉ phục vụ cho GET và POST theo tiêu chuẩn, nhưng công việc này là vô địch. Urllib2.build_opener (urllib2.HTTPHandler) có thể được sử dụng lại trong nhiều cuộc gọi không?
WeNeedAnswers

46

Httplib có vẻ như là một sự lựa chọn sạch hơn.

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

Không sử dụng omeplib nếu bạn (hoặc bất kỳ người dùng tiềm năng nào của bạn) cần hỗ trợ proxy. Xem bài viết này để biết chi tiết.
Jason R. Coombs

Tại sao bạn nói thế? Bài viết của bạn nói rõ rằng nó hoạt động. Xem câu trả lời của Rolf Wester, anh ta nói rằng urllib thất bại nhưng omeplib hoạt động.
Spooles

omeplib chỉ hoạt động khi người dùng kết nối rõ ràng với proxy và sửa đổi yêu cầu để bao gồm URL đầy đủ trong tham số GET. Lý do urllib thất bại là vì http_proxy không được đặt đúng. urllib sử dụng omeplib dưới các cảnh, nhưng cũng xử lý các chuyển hướng, proxy, v.v.
Jason R. Coombs

Trong khi giải pháp này sẽ hoạt động, một trong những yêu cầu sử dụng đơn giản hơn, thanh lịch hơn và theo tôi thì tốt hơn.
tgrosinger

1
@tgrosinger Tôi đồng ý. Câu trả lời này đã được đăng trước khi yêu cầu tồn tại. Cho đến bây giờ, trường hợp duy nhất mà giải pháp này sẽ tốt hơn là nếu chỉ có Thư viện tiêu chuẩn Python mới khả dụng. Nếu không, tôi cũng khuyên bạn nên sử dụng các yêu cầu.
Spooles

8

Bạn nên xem qua mô-đun omeplib . Nó sẽ cho phép bạn thực hiện bất kỳ loại yêu cầu HTTP nào bạn muốn.


Giải pháp hay, pythonic yên tĩnh nhưng hơi gần với kim loại và liên quan đến việc viết rất nhiều mã khác
Rory

8

Tôi cần phải giải quyết vấn đề này một thời gian trước để tôi có thể đóng vai trò là khách hàng cho API RESTful. Tôi đã giải quyết trên omeplib2 vì nó cho phép tôi gửi PUT và XÓA cùng với GET và POST. Httplib2 không phải là một phần của thư viện tiêu chuẩn nhưng bạn có thể dễ dàng lấy nó từ cửa hàng phô mai.


2
omeplib2 là phần mềm bỏ biên giới. Nó có một danh sách dài các lỗi không được trộn lẫn mặc dù có sự đóng góp của cộng đồng (bản vá). Tôi đề nghị suy nghĩ hai lần trước khi sử dụng omeplib2 trong bất kỳ môi trường sản xuất nào.
Jason R. Coombs

8

Bạn có thể sử dụng thư viện yêu cầu, nó đơn giản hóa mọi thứ rất nhiều so với cách tiếp cận urllib2. Đầu tiên cài đặt nó từ pip:

pip install requests

Thêm về yêu cầu cài đặt .

Sau đó thiết lập yêu cầu đặt:

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)

Xem phần khởi động nhanh cho thư viện yêu cầu . Tôi nghĩ rằng điều này đơn giản hơn nhiều so với urllib2 nhưng không yêu cầu gói bổ sung này phải được cài đặt và nhập khẩu.


Không yêu cầu hỗ trợ PUT là tốt?
Jeef

yêu cầu hỗ trợ nhận, đặt, đăng, xóa đầu và các tùy chọn. Đã sửa lỗi sử dụng put. Kiểm tra yêu cầu nhanh chóng bắt đầu.
radtek

@RPradeep Cảm ơn vì điều đó.
radtek

8

Điều này đã được thực hiện tốt hơn trong python3 và được ghi lại trong tài liệu stdlib

Các urllib.request.Requestlớp học đã đạt được một method=...tham số trong python3.

Một số cách sử dụng mẫu:

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

6

Tôi cũng giới thiệu omeplib2 của Joe Gregario. Tôi sử dụng điều này thường xuyên thay vì omeplib trong lib tiêu chuẩn.


3

Bạn đã xem put put chưa? Tôi đã sử dụng nó trong quá khứ. Bạn cũng có thể hack yêu cầu của riêng bạn với urllib.


Tôi thực sự không muốn sử dụng thư viện http của một số người ngẫu nhiên
Rory

cố gắng nhập nhập đặt # pip cài đặt đặt Tải xuống / giải nén đặt Không thể tìm thấy bất kỳ tải xuống nào đáp ứng yêu cầu đặt Dọn dẹp ... Không tìm thấy phân phối nào cho đặt
Ashish Karpe

# tail -f /root/.pip/pip.log TracBack (cuộc gọi gần đây nhất vừa qua): Tệp "/usr/lib/python2.7/dist-packages/pip/basecommand.py", dòng 122, trong trạng thái chính = self.run (tùy chọn, đối số) Tệp "/usr/lib/python2.7/dist-packages/pip/commands/install.py", dòng 278, trong run request_set.prepare_files (finder, force_root_egg_info = self.bundle, bundle = self.bundle) Tập tin "/usr/lib/python2.7/dist-packages/pip/req.py", dòng 1178, trong Chuẩn bị_files
Ashish Karpe

url = finder.find numquirement (req_to_install, nâng cấp = self.upTHER) Tệp "/usr/lib/python2.7/dist-packages/pip/index.py", dòng 277, trong find_Vquirement nâng phân phốiNotFound ('Không tìm thấy phân phối cho% s '% req) Phân phốiNotFound: Không tìm thấy phân phối nào cho đặt
Ashish Karpe

2

Tất nhiên, bạn có thể tự cuộn với các thư viện tiêu chuẩn hiện có ở mọi cấp độ từ ổ cắm cho đến tinh chỉnh urllib.

http://pycurl.sourceforge.net/

"PyCurl là giao diện Python cho libcurl."

"libcurl là thư viện chuyển URL phía máy khách miễn phí và dễ sử dụng, ... hỗ trợ ... HTTP PUT"

"Hạn chế chính với PycURL là nó là một lớp mỏng tương đối so với libcurl mà không có bất kỳ hệ thống phân cấp lớp Pythonic tốt đẹp nào. Điều này có nghĩa là nó có một đường cong học tập hơi dốc trừ khi bạn đã quen thuộc với API C của libcurl."


Tôi chắc chắn rằng nó sẽ hoạt động, nhưng tôi muốn một cái gì đó nhiều hơn một chút pythonic
Rory

2

Nếu bạn muốn ở trong thư viện chuẩn, bạn có thể phân lớp 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

Một cách thích hợp hơn để làm điều này với requestssẽ là:

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

Điều này đặt ra một ngoại lệ nếu có lỗi trong yêu cầu PUT HTTP.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.