Чи є спосіб зробити HTTP PUT в python


220

Мені потрібно завантажити деякі дані на сервер за допомогою HTTP PUTв python. З мого короткого прочитання документів urllib2, це лише HTTP POST. Чи є спосіб зробити HTTP PUTв python?

Відповіді:


312

У минулому я використовував різні версії python HTTP, і я зупинився на " Запити " як свого улюбленого. Існуючі лібри мали досить корисні інтерфейси, але код може закінчитися декількома рядками занадто довгими для простих операцій. Основний 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

3
Використовуйте json=payloadпараметр, якщо ви хочете, щоб дані були в тілі.
ManuelSchneid3r

1
Хочу швидко зазначити, що цей інтерфейс кращий за інші відповіді, оскільки це функціональне програмування. Навіщо створювати об’єкт, коли функція з простими структурами даних як параметри буде робити. Я б хотів, щоб інші бібліотеки пітона дотримувалися цього.
Марк

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
Ця відповідь була блискучою, коли вона була написана, але в наш час набагато простіше використовувати пакет "запитів", натомість див. Відповідь Джона Картера. "Запити" - це ніяк не іграшка - вона надзвичайно здатна.
Джонатан Хартлі

5
Ця відповідь є канонічною, але застарілою. Будь ласка, подумайте про використання requestsбібліотеки.
jsalonen

13
Дякую, я не хотів нічого використовувати поза стандартною бібліотекою python, і це працює ідеально. Я не зовсім розумію, чому urllib2 призначений лише для GET і POST як стандарт, але ця робота навколо є чемпіонською. Чи можна urllib2.build_opener (urllib2.HTTPHandler) повторно використовувати у кількох дзвінках?
WeNeedAnswers

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, якщо вам (або комусь із ваших потенційних користувачів) потрібна підтримка проксі. Детальну інформацію див. У цій статті .
Джейсон Р. Кумбс

Чому ти це сказав? У вашій статті чітко зазначено, що вона працює. Дивіться відповідь Рольфа Вестера, він говорить, що urllib не працює, але httplib працює.
Spooles

httplib працює лише тоді, коли користувач явно підключається до проксі і змінює запит, щоб включити повну URL-адресу в параметр GET. Причина urllib не вдалася через те, що http_proxy встановлений неправильно. urllib використовує httplib під сценами, але також обробляє переадресації, проксі, тощо.
Джейсон Р. Кумбс

Хоча це рішення працювало б, той, хто використовує запити, набагато простіший, елегантніший і, на мою думку, кращий.
tgrosinger

1
@tgrosinger Я згоден. Ця відповідь була розміщена до того, як існували запити. На сьогодні єдиний випадок, коли це рішення було б кращим, якби була доступна лише стандартна бібліотека Python. В іншому випадку я також рекомендую використовувати запити.
Spooles

8

Ви повинні ознайомитись з модулем httplib . Це повинно дозволяти вам робити будь-який тип запиту HTTP, який ви хочете.


Приємне рішення, тихий пітонічний, але трохи занадто близький до металу та включає вже багато інших кодів
Rory,

8

Мені потрібно було ще раз вирішити цю проблему, щоб я міг виступати клієнтом API RESTful. Я влаштувався на httplib2, тому що це дозволило мені надсилати PUT і DELETE на додаток до GET та POST. Httplib2 не входить до стандартної бібліотеки, але ви можете легко отримати його в магазині сирів.


2
httplib2 - прикордонне програмне забезпечення. У ньому довгий список помилок, які не виправляються, незважаючи на внески громади (виправлення). Пропоную подумати двічі, перш ніж використовувати httplib2 в будь-яких виробничих умовах.
Джейсон Р. Кумбс

8

Ви можете використовувати бібліотеку запитів, це значно спрощує речі порівняно з підходом urllib2. Спочатку встановіть його з pip:

pip install requests

Детальніше про встановлення запитів .

Потім встановіть запит put:

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?
Jeef

Підтримка запитів отримати, поставити, опублікувати, видалити голову та параметри. Виправлено приклад використання put. Ознайомтеся із запитами.
radtek

@RPradeep Дякую за це.
radtek

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,

намагаюся імпортувати поставити отримання # pip install put Завантаження / розпакування put Не вдалося знайти завантаження, які задовольняли б вимогу
Почистити

# tail -f /root/.pip/pip.log Traceback (останній дзвінок останній): Файл "/usr/lib/python2.7/dist-packages/pip/basecommand.py", рядок 122, у головному статусі = self.run (параметри, аргументи) Файл "/usr/lib/python2.7/dist-packages/pip/commands/install.py", рядок 278, у виконанні Requir_set.prepare_files (finder, force_root_egg_info = self.bundle, bundle = self.bundle) Файл "/usr/lib/python2.7/dist-packages/pip/req.py", рядок 1178, у
файлах Prepa_files

url = finder.find_requirement (req_to_install, upgrade = self.upgrade) Файл "/usr/lib/python2.7/dist-packages/pip/index.py", рядок 277, у find_requirement підніміть DistributionNotFound ("Дистрибуції взагалі не знайдено для% s '% req) DistributionNotFound: Дистрибуції взагалі не знайдені для put
Ashish Karpe

2

Звичайно, ви можете згорнути власні файли з існуючими стандартними бібліотеками на будь-якому рівні, починаючи від сокетів до налаштування URL-адреси.

http://pycurl.sourceforge.net/

"PyCurl - це інтерфейс Python для лібкурлу."

"libcurl - це безкоштовна і проста у використанні бібліотека передачі URL-адрес на стороні клієнта, ... підтримує ... HTTP PUT"

"Основним недоліком PycURL є те, що він є відносно тонким шаром над libcurl без будь-якої з цих приємних ієрархій класів Pythonic. Це означає, що він має дещо круту криву навчання, якщо ви вже не знайомі з API C libcurl."


Я впевнений, що це спрацює, але мені хочеться чогось більш пітонічного
Рорі,

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 є помилка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.