Python'da HTTP PUT yapmanın herhangi bir yolu var mı


220

Bazı verileri PUTpython HTTP kullanarak bir sunucuya yüklemeniz gerekiyor . Urllib2 belgelerini okuduğumda sadece HTTP yapıyor POST. PUTPython'da HTTP yapmanın bir yolu var mı ?

Yanıtlar:


312

Geçmişte çeşitli python HTTP kütüphanelerini kullandım ve favorilerim olarak ' İstekler'e karar verdim. Mevcut kütüphanelerin oldukça kullanışlı arayüzleri vardı, ancak kod basit işlemler için birkaç satır uzunluğunda olabilir. İsteklerde temel bir PUT şöyle görünür:

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

Daha sonra yanıt durum kodunu aşağıdakilerle kontrol edebilirsiniz:

r.status_code

veya şununla yanıt:

r.content

İsteklerde hayatınızı kolaylaştıracak çok fazla şeker hastası ve kısayol vardır.


11
Yukarıdaki kod son derece basit görünse de, 'isteklerin' hiçbir şekilde eksik veya yetersiz güç olduğunu anlamayın. Oldukça düzenli bir arayüz ile son derece yeteneklidir.
Jonathan Hartley

5
Acaba bu cevabı, en yüksek oyu alan yeni cevap haline gelene kadar kademeli olarak oy toplamak ne kadar sürer?
Jonathan Hartley

2
Bunun ne kadar harika olduğunu anlamıyorsunuz !!! Crummy java kütüphanesi ile mücadele ediyordum! ... sanırım seni "İstekler" i işaret ettiğin için seviyorum!
Shehaaz

3
json=payloadVerilerin gövdede olmasını istiyorsanız parametreyi kullanın .
ManuelSchneid3r

1
Hızlı bir şekilde bu arayüzün diğer cevaptan daha iyi olduğunu belirtmek istiyorum, çünkü fonksiyonel programlama. Parametreler gibi basit veri yapılarına sahip bir işlev yapıldığında neden bir nesne yaratabilirsiniz. Keşke diğer python kütüphaneleri de onu takip etsin.
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
Kirli bir kesmek gibi görünüyor, ama zarif ve tamamen çalışıyor gibi görünüyor
Rory

6
Eğer urllib2 alt sınıf için olsaydı bir kesmek daha az olurdu. Maymun yama yama yerine isteyin.
Jason R.Combs

23
Bu cevap yazıldığı zaman mükemmeldi, ama bugünlerde 'istekler' paketini kullanmak çok daha kolay, bkz. John Carter'ın cevabı. 'Talepler' hiçbir şekilde bir oyuncak değildir - son derece yeteneklidir.
Jonathan Hartley

5
Bu cevap standarttır, ancak güncel değildir. Lütfen requestsbunun yerine kütüphane kullanmayı düşünün .
jsalonen

13
Teşekkür ederim, standart python kütüphanesi dışında hiçbir şey kullanmak istemedim ve bu mükemmel çalışıyor. Urllib2'nin neden sadece standart olarak GET ve POST için yiyecek ve içecek sağlamak üzere tasarlandığını tam olarak anlamıyorum, ancak bu çözüm şampiyon. Urllib2.build_opener (urllib2.HTTPHandler) birden fazla çağrıda tekrar kullanılabilir mi?
WeNeedAnswers

46

Httplib daha temiz bir seçim gibi görünüyor.

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

Siz (veya potansiyel kullanıcılarınızdan herhangi biri) proxy desteğine ihtiyacınız varsa httplib kullanmayın. Ayrıntılar için bu makaleye bakın.
Jason R.Combs

Bunu neden dedin ki? Makaleniz açıkça çalıştığını belirtiyor. Rolf Wester'in cevabına bakın, urllib'in başarısız olduğunu ancak httplib'in çalıştığını söylüyor.
Makaralar

httplib yalnızca kullanıcı proxy'ye açıkça bağlandığında ve GET parametresine tam URL'yi dahil etme isteğinde değişiklik yaptığında çalışır. Urllib'in başarısız olmasının nedeni, http_proxy'nin düzgün ayarlanmamış olmasıdır. urllib sahnelerin altında httplib kullanıyor, ancak yönlendirmeleri, vekilleri vb. yönetiyor
Jason R. Coombs

Bu çözüm işe yarayacak olsa da, istekleri kullanan kişi çok daha basit, zarif ve bence daha iyidir.
tgrosinger

1
@tgrosinger Kabul ediyorum. Bu cevap istekler var olmadan önce gönderildi. Şu andan itibaren bu çözümün daha iyi olacağı tek durum, sadece Python Standart Kütüphanesi'nin mevcut olup olmadığıdır. Aksi takdirde, istekleri de kullanmanızı öneririm.
Makaralar


8

Ben RESTful API için bir istemci olarak hareket böylece ben bu sorunu bir süre önce çözmek gerekiyordu. Httplib2'ye yerleştim çünkü GET ve POST'a ek olarak PUT ve DELETE göndermeme izin verdi. Httplib2 standart kütüphanenin bir parçası değildir, ancak peynir dükkanından kolayca alabilirsiniz.


2
httplib2 sınırda vazgeçilmez yazılımdır. Topluluk katkılarına (düzeltme ekleri) rağmen düzeltilmeyen uzun bir hata listesi var. Herhangi bir üretim ortamında httplib2'yi kullanmadan önce iki kez düşünmenizi öneririm.
Jason R.Combs

8

İstek kütüphanesini kullanabilirsiniz, urllib2 yaklaşımına kıyasla işleri çok basitleştirir. İlk önce pip'ten kurun:

pip install requests

Yükleme istekleri hakkında daha fazla bilgi .

Sonra put isteğini ayarlayın:

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)

İstekler kitaplığı için hızlı başlatmaya bakın . Bunun urllib2'den çok daha basit olduğunu düşünüyorum, ancak bu ek paketin yüklenmesini ve içe aktarılmasını gerektiriyor.


İstekler PUT'u da desteklemiyor mu?
Jeef

istekleri destekler almak, koymak, göndermek, silmek kafa ve seçenekleri. Put kullanımı örneği düzeltildi. Checks istekleri hızlı başlangıç.
radtek

@RPradeep Bunun için teşekkürler.
radtek

8

Bu, python3'te daha iyi hale getirildi ve stdlib belgelerinde belgelendi

urllib.request.RequestSınıf kazanmıştır method=...python3 parametreyi.

Bazı örnek kullanımlar:

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


3

Put.py'a bir göz attınız mı? Geçmişte kullandım. Ayrıca urllib ile kendi isteğinizi de hackleyebilirsiniz.


Gerçekten bazı rastgele adamlar http kütüphane kullanmak istemiyorum
Rory

ithal koymak çalışıyor # pip install put almak İndirmek / açmak koymak koymak koymak gereklilik karşılayan herhangi bir indirme bulunamadı Temizlik ... koymak için hiçbir dağıtım bulunamadı
Ashish Karpe

# tail -f /root/.pip/pip.log Geri izleme (en son çağrı): Ana durumdaki "/usr/lib/python2.7/dist-packages/pip/basecommand.py", satır 122 dosyası = self.run (seçenekler, bağımsız değişkenler) Dosya "/usr/lib/python2.7/dist-packages/pip/commands/install.py", satır 278, çalışma gereksinimi_set.prepare_files (finder, force_root_egg_info = self.bundle, paket) = self.bundle) Hazırlama dosyalarında "/usr/lib/python2.7/dist-packages/pip/req.py", satır 1178'deki dosya
Ashish Karpe

url = finder.find_requirement (req_to_install, yükseltme = self.upgrade) Dosya "/usr/lib/python2.7/dist-packages/pip/index.py", satır 277, find_requirement dosyasında DistributionNotFound ('Dağılım bulunamadı) % s '% req) DistributionNotFound: put için hiç dağıtım bulunamadı
Ashish Karpe

2

Tabii ki mevcut standart kütüphanelerle soketlerden ince ayar urllibine kadar kendi seviyenizi kullanabilirsiniz.

http://pycurl.sourceforge.net/

"PyCurl libcurl bir Python arabirimidir."

"libcurl ücretsiz ve kullanımı kolay bir istemci tarafı URL transfer kütüphanesi, ... destekler ... HTTP PUT"

"PycURL ile en büyük dezavantajı, bu güzel Pythonic sınıfı hiyerarşilerinden herhangi biri olmadan libcurl üzerine nispeten ince bir katman olmasıdır. Bu, libcurl'un C API'sine aşina değilseniz, biraz dik bir öğrenme eğrisine sahip olduğu anlamına gelir."


İşe yarayacağından eminim, ama biraz daha pitonik bir şey istiyorum
Rory

2

Standart kitaplığın içinde kalmak istiyorsanız, aşağıdaki sınıfları kullanabilirsiniz 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

Bunu yapmanın daha uygun bir yolu 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 isteğinde bir hata varsa bu bir istisna oluşturur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.