Чи є спосіб зробити 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.