Apakah ada cara untuk melakukan HTTP PUT dengan python

220

Saya perlu mengunggah beberapa data ke server menggunakan HTTP PUTdengan python. Dari bacaan singkat saya tentang urllib2 docs, ia hanya melakukan HTTP POST. Apakah ada cara untuk melakukan HTTP PUTdengan python?

Rory
sumber

Jawaban:

311

Saya telah menggunakan berbagai libs HTTP python di masa lalu, dan saya telah memilih ' Permintaan ' sebagai favorit saya. Lib yang ada memiliki antarmuka yang cukup bisa digunakan, tetapi kode dapat berakhir menjadi beberapa baris terlalu lama untuk operasi sederhana. PUT dasar dalam permintaan terlihat seperti:

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

Anda kemudian dapat memeriksa kode status respons dengan:

r.status_code

atau tanggapan dengan:

r.content

Permintaan memiliki banyak gula dan jalan pintas yang akan membuat hidup Anda lebih mudah.

John Carter
sumber
11
Meskipun kode di atas terlihat sangat sederhana, jangan menyimpulkan bahwa 'permintaan' sama sekali kurang atau kurang bertenaga. Ini sangat mampu, hanya dengan antarmuka yang sangat rapi.
Jonathan Hartley
5
Saya ingin tahu berapa lama waktu yang dibutuhkan jawaban ini untuk secara bertahap mengumpulkan suara sampai menjadi jawaban baru dengan suara tertinggi?
Jonathan Hartley
2
Anda tidak mengerti betapa hebatnya ini !!! Saya sedang berjuang dengan perpustakaan java payah! ... Saya pikir saya agak mencintaimu karena menunjuk ke "Permintaan"!
Shehaaz
3
Gunakan json=payloadparameter jika Anda ingin data berada di tubuh.
ManuelSchneid3r
1
Saya ingin dengan cepat menunjukkan bahwa antarmuka ini lebih baik daripada jawaban yang lain, karena ini pemrograman fungsional. Mengapa membuat objek ketika fungsi dengan struktur data sederhana sebagai parameter akan dilakukan. Saya berharap perpustakaan python lain akan mengikutinya.
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)
Florian Bösch
sumber
4
Sepertinya sedikit hack kotor, tetapi tampaknya bekerja dengan elegan dan lengkap
Rory
6
Akan lebih sedikit peretasan jika Anda menggunakan subclass urllib2.Request alih-alih menambal monyet.
Jason R. Coombs
23
Jawaban ini sangat brilian ketika ditulis, tetapi saat ini jauh lebih mudah untuk menggunakan paket 'permintaan', lihat jawaban John Carter. 'Permintaan' sama sekali bukan mainan - itu sangat mampu.
Jonathan Hartley
5
Jawaban ini kanonik, tetapi ketinggalan zaman. Tolong, pertimbangkan untuk menggunakan requestsperpustakaan sebagai gantinya.
jsalonen
13
Terima kasih, saya tidak ingin menggunakan apa pun di luar perpustakaan python standar dan ini berfungsi sempurna. Saya tidak begitu mengerti mengapa urllib2 dirancang hanya untuk memenuhi GET dan POST sebagai standar, tetapi pekerjaan ini adalah juara. Bisakah urllib2.build_opener (urllib2.HTTPHandler) digunakan kembali dalam beberapa panggilan?
WeNeedAnswers
46

Httplib sepertinya merupakan pilihan yang lebih bersih.

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
Gulungan
sumber
Jangan gunakan httplib jika Anda (atau salah satu pengguna potensial Anda) memerlukan dukungan proxy. Lihat artikel ini untuk detailnya.
Jason R. Coombs
Mengapa Anda mengatakan itu? Artikel Anda dengan jelas menyatakan bahwa itu berfungsi. Lihat jawaban Rolf Wester, ia mengatakan bahwa urllib gagal tetapi httplib berfungsi.
Kumparan
httplib hanya berfungsi ketika pengguna secara eksplisit terhubung ke proksi dan memodifikasi permintaan untuk memasukkan URL lengkap dalam parameter GET. Alasan urllib gagal adalah karena http_proxy tidak disetel dengan benar. urllib menggunakan httplib di bawah layar, tetapi juga menangani pengalihan, proksi, dll.
Jason R. Coombs
Sementara solusi ini akan berhasil, yang menggunakan permintaan jauh lebih sederhana, elegan, dan menurut saya lebih baik
tgrosinger
1
@ tgrosinger saya setuju. Jawaban ini diposting sebelum permintaan ada. Sampai sekarang, satu-satunya kasus di mana solusi ini akan lebih baik adalah jika hanya Python Standard Library yang tersedia. Kalau tidak, saya juga merekomendasikan untuk menggunakan permintaan.
Kumparan
8

Anda harus melihat pada modul httplib . Seharusnya Anda membiarkan permintaan HTTP apa pun yang Anda inginkan.

John Montgomery
sumber
Solusi yang bagus, pythonic yang tenang tetapi agak terlalu dekat dengan logam dan melibatkan penulisan banyak kode lain
Rory
8

Saya perlu menyelesaikan masalah ini beberapa waktu lalu sehingga saya bisa bertindak sebagai klien untuk RESTful API. Saya memilih httplib2 karena memungkinkan saya mengirim PUT dan DELETE selain GET dan POST. Httplib2 bukan bagian dari perpustakaan standar tetapi Anda dapat dengan mudah mendapatkannya dari toko keju.

Mike
sumber
2
httplib2 adalah perangkat batas. Ini memiliki daftar panjang bug yang tidak diperbaiki meskipun ada kontribusi komunitas (tambalan). Saya sarankan berpikir dua kali sebelum menggunakan httplib2 di lingkungan produksi mana pun.
Jason R. Coombs
8

Anda dapat menggunakan perpustakaan permintaan, itu menyederhanakan banyak hal dibandingkan dengan mengambil pendekatan urllib2. Pertama instal dari pip:

pip install requests

Lebih lanjut tentang menginstal permintaan .

Kemudian atur permintaan 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)

Lihat quickstart untuk perpustakaan permintaan . Saya pikir ini jauh lebih sederhana daripada urllib2 tetapi memang membutuhkan paket tambahan ini untuk diinstal dan diimpor.

radtek
sumber
Bukankah permintaan juga mendukung PUT?
Astaga
permintaan mendukung dapatkan, masukkan, posting, hapus kepala dan opsi. Memperbaiki contoh untuk menggunakan put. Lihat permintaan mulai cepat.
radtek
@RPradeep Terima kasih untuk itu.
radtek
8

Ini dibuat lebih baik di python3 dan didokumentasikan dalam dokumentasi stdlib

The urllib.request.Requestkelas memperoleh method=...parameter dalam python3.

Beberapa penggunaan sampel:

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

Saya juga merekomendasikan httplib2 oleh Joe Gregario. Saya menggunakan ini secara teratur, bukan httplib di lib standar.

Corey Goldberg
sumber
3

Apakah Anda sudah melihat put.py ? Saya sudah menggunakannya di masa lalu. Anda juga dapat meretas permintaan Anda sendiri dengan urllib.

William Keller
sumber
Saya tidak benar-benar ingin menggunakan beberapa perpustakaan http orang-orang acak
Rory
coba impor put, dapatkan # pip instal put, unduh / unduh put. Tidak dapat menemukan unduhan yang memenuhi persyaratan, Bersihkan ... Tidak ada distribusi yang ditemukan untuk put
Ashish Karpe
# tail -f /root/.pip/pip.log Traceback (panggilan terakhir terakhir): File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", baris 122, dalam status utama = self.run (options, args) File "/usr/lib/python2.7/dist-packages/pip/commands/install.py", baris 278, dalam menjalankan requirement_set.prepare_files (finder, force_root_egg_info = self.bundle, bundle = self.bundle) File "/usr/lib/python2.7/dist-packages/pip/req.py", baris 1178, di prep_files
Ashish Karpe
url = finder.find_requirement (req_to_install, upgrade = self.upgrade) File "/usr/lib/python2.7/dist-packages/pip/index.py", baris 277, di find_requirement, naik DistributionNotFound ('Tidak ada distribusi sama sekali yang ditemukan untuk% s '% req) DistributionNotFound: Tidak ditemukan distribusi untuk put
Ashish Karpe
2

Anda tentu saja dapat memutar sendiri dengan perpustakaan standar yang ada di tingkat mana saja dari soket hingga tweaker urllib.

http://pycurl.sourceforge.net/

"PyCurl adalah antarmuka Python ke libcurl."

"libcurl adalah pustaka transfer URL sisi-klien gratis dan mudah digunakan, ... mendukung ... HTTP PUT"

"Kelemahan utama dengan PycURL adalah bahwa itu adalah lapisan yang relatif tipis di atas libcurl tanpa ada hierarki kelas Pythonic yang bagus. Ini berarti ia memiliki kurva belajar yang agak curam kecuali Anda sudah terbiasa dengan API C libcurl."

Wnoise
sumber
Saya yakin itu akan berhasil, tetapi saya ingin sesuatu yang sedikit lebih pythonic
Rory
2

Jika Anda ingin tetap berada di perpustakaan standar, Anda dapat mensubklasifikasikan 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)
Wilfred Hughes
sumber
0

Cara yang lebih tepat untuk melakukan ini requestsadalah:

import requests

payload = {'username': 'bob', 'email': '[email protected]'}

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

Ini menimbulkan pengecualian jika ada kesalahan dalam permintaan HTTP PUT.

Adam Erickson
sumber