มีวิธีใดที่จะทำ HTTP PUT ในไพ ธ อน


220

ฉันต้องการอัปโหลดข้อมูลบางอย่างไปยังเซิร์ฟเวอร์โดยใช้ HTTP PUTใน python จากการอ่านเอกสาร urllib2 ของฉันสั้น ๆ มันใช้ HTTP POSTเท่านั้น มีวิธีใดที่จะทำ HTTP PUTใน python หรือไม่?

คำตอบ:


312

ฉันเคยใช้ python HTTP libs ที่หลากหลายในอดีตและฉันตัดสินว่า ' คำขอ ' เป็นรายการโปรดของฉัน libs ที่มีอยู่มีอินเทอร์เฟซที่ใช้งานได้ค่อนข้างดี แต่โค้ดสามารถจบลงด้วยการมีสองสามบรรทัดยาวเกินไปสำหรับการดำเนินการอย่างง่าย PUT พื้นฐานในคำขอดูเหมือนว่า:

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

จากนั้นคุณสามารถตรวจสอบรหัสสถานะการตอบกลับด้วย:

r.status_code

หรือการตอบสนองด้วย:

r.content

คำขอมีซินแท็กซ์น้ำตาลและทางลัดมากมายที่จะทำให้ชีวิตของคุณง่ายขึ้น


11
แม้ว่าโค้ดข้างต้นนั้นดูเรียบง่ายมาก แต่ก็ไม่ควรอนุมานว่า 'คำขอ' นั้นขาดหรืออยู่ในรูปแบบใด ๆ มันมีความสามารถอย่างยิ่งเพียงแค่มีอินเตอร์เฟซที่เป็นระเบียบ
Jonathan Hartley

5
ฉันสงสัยว่าจะต้องใช้เวลานานเท่าไรในการตอบคำถามนี้เพื่อสะสมคะแนนไปเรื่อย ๆ จนกว่ามันจะกลายเป็นคำตอบที่ได้รับคะแนนสูงสุดใหม่?
Jonathan Hartley

2
คุณไม่เข้าใจว่ามันยอดเยี่ยมแค่ไหน !!! ฉันกำลังดิ้นรนกับห้องสมุด java crummy! ... ฉันคิดว่าฉันรักคุณมากที่ชี้ไปที่ "คำขอ"!
Shehaaz

3
ใช้json=payloadพารามิเตอร์หากคุณต้องการให้ข้อมูลอยู่ในร่างกาย
ManuelSchneid3r

1
ฉันต้องการชี้ให้เห็นอย่างรวดเร็วว่าอินเทอร์เฟซนี้ดีกว่าคำตอบอื่น ๆ เพราะมันเป็นฟังก์ชั่นการเขียนโปรแกรม ทำไมต้องสร้างวัตถุเมื่อฟังก์ชั่นที่มีโครงสร้างข้อมูลแบบง่าย ๆ ตามที่พารามิเตอร์จะทำ ฉันหวังว่าห้องสมุดไพ ธ อนอื่น ๆ
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
ดูเหมือนแฮ็คสกปรกสักหน่อย แต่ดูเหมือนว่าจะทำงานได้อย่างสวยงามและสมบูรณ์แบบ
Rory

6
มันจะน้อยกว่าการแฮ็คถ้าคุณต้อง subclass urllib2.Request แทนการปะแก้ลิง
Jason R. Coombs

23
คำตอบนี้ยอดเยี่ยมเมื่อเขียน แต่ทุกวันนี้มันง่ายกว่าการใช้แพ็คเกจ 'คำขอ' แทนดูคำตอบของ John Carter 'คำขอ' นั้นไม่มีของเล่นเลยมันมีความสามารถอย่างยิ่ง
Jonathan Hartley

5
คำตอบนี้เป็นที่ยอมรับ แต่ล้าสมัย โปรดพิจารณาใช้requestsห้องสมุดแทน
jsalonen

13
ขอบคุณฉันไม่ต้องการใช้อะไรนอกเหนือจากห้องสมุดไพ ธ อนแบบมาตรฐานและใช้งานได้สมบูรณ์แบบ ฉันไม่เข้าใจว่าทำไม 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 หากคุณ (หรือผู้ใช้ที่มีศักยภาพของคุณ) ต้องการการสนับสนุนพรอกซี ดูบทความนี้สำหรับรายละเอียด
Jason R. Coombs

ทำไมคุณพูดเช่นนั้น? บทความของคุณระบุอย่างชัดเจนว่าทำงานได้ดี ดูคำตอบของ Rolf Wester เขาบอกว่า urllib นั้นล้มเหลว แต่ httplib ใช้ได้
Spooles

httplib ใช้งานได้เฉพาะเมื่อผู้ใช้เชื่อมต่อกับพร็อกซีอย่างชัดเจนและแก้ไขคำขอเพื่อรวม URL แบบเต็มในพารามิเตอร์ GET สาเหตุ urllib ล้มเหลวเนื่องจาก http_proxy ไม่ได้ตั้งอย่างถูกต้อง urllib ใช้ httplib ภายใต้ฉาก แต่ยังจัดการเปลี่ยนเส้นทางพร็อกซี ฯลฯ
เจสันคูมบ์สอาร์

ในขณะที่โซลูชันนี้ใช้งานได้การใช้คำขอนั้นเรียบง่ายสวยงามและในความคิดของฉันก็ดีกว่า
tgrosinger

1
@tgrosinger ฉันเห็นด้วย คำตอบนี้ถูกโพสต์ก่อนคำขอมีอยู่ ณ ตอนนี้กรณีเดียวที่โซลูชันนี้จะดีกว่าคือถ้ามี Python Standard Library เท่านั้นที่พร้อมใช้งาน มิฉะนั้นฉันก็จะแนะนำให้ใช้คำขอ
Spooles

8

คุณควรมีลักษณะที่เป็นhttplib โมดูล ควรให้คุณสร้างคำขอ HTTP ที่คุณต้องการ


ทางออกที่ดี, pythonic ที่เงียบสงบ แต่อยู่ใกล้กับโลหะมากเกินไปและเกี่ยวข้องกับการเขียนรหัสอื่น ๆ จำนวนมากแล้ว
Rory

8

ฉันจำเป็นต้องแก้ปัญหานี้ด้วยในขณะที่ฉันสามารถทำหน้าที่เป็นลูกค้าของ RESTful API ได้ ฉันตัดสินที่ httplib2 เพราะอนุญาตให้ฉันส่ง PUT และ DELETE เพิ่มเติมจาก GET และ POST Httplib2 ไม่ได้เป็นส่วนหนึ่งของห้องสมุดมาตรฐาน แต่คุณสามารถหาซื้อได้จากร้านชีส


2
httplib2 เป็นซอฟต์แวร์ที่ใช้ในการวางแนว มีรายการข้อผิดพลาดจำนวนมากที่ไม่ได้รวมแม้จะมีส่วนร่วมกับชุมชน (แพตช์) ฉันขอแนะนำให้คิดสองครั้งก่อนที่จะใช้ httplib2 ในสภาพแวดล้อมการผลิตใด ๆ
Jason R. Coombs

8

คุณสามารถใช้ไลบรารีคำขอมันทำให้สิ่งต่าง ๆ ง่ายขึ้นมากเมื่อเปรียบเทียบกับแนวทาง urllib2 ก่อนติดตั้งจาก pip:

pip install requests

เพิ่มเติมเกี่ยวกับการร้องขอการติดตั้ง

จากนั้นตั้งค่าคำขอวาง:

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)

ดูQuickStart ห้องสมุดการร้องขอ ฉันคิดว่ามันง่ายกว่า urllib2 มาก แต่ต้องติดตั้งและนำเข้าแพ็คเกจเพิ่มเติมนี้


คำขอไม่สนับสนุน PUT ด้วยหรือไม่
Jeef

คำขอรองรับรับใส่โพสต์ลบหัวและตัวเลือก แก้ไขตัวอย่างที่จะใช้วาง ตรวจสอบคำขอเริ่มต้นอย่างรวดเร็ว
radtek

@ Radradeep ขอบคุณสำหรับสิ่งนั้น
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

พยายามนำเข้า put getting # pip install put การดาวน์โหลด / คลายการบรรจุไม่พบการดาวน์โหลดใด ๆ ที่ตรงตามข้อกำหนดวางล้างค่า ... ไม่พบการแจกแจงทั้งหมดสำหรับการวาง
Ashish Karpe

# tail -f /root/.pip/pip.log การติดตามย้อนกลับ (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "/usr/lib/python2.7/dist-packages/pip/basecommand.py", บรรทัดที่ 122, ในสถานะหลัก = self.run (ตัวเลือก args) ไฟล์ "/usr/lib/python2.7/dist-packages/pip/commands/install.py", บรรทัด 278, ในการรัน Requ_set.prepare_files (ค้นหา, force_root_egg_info = self.bundle, ชุดรวม = self.bundle) ไฟล์ "/usr/lib/python2.7/dist-packages/pip/req.py", บรรทัดที่ 1178, ใน prepare_files
Ashish Karpe

url = finder.find_requirement (req_to_install, upgrade = self.upgrade) ไฟล์ "/usr/lib/python2.7/dist-packages/pip/index.py", บรรทัด 277, ใน find_requirement เพิ่มการแจกแจง Nototound ('ไม่พบการแจกจ่ายเลย สำหรับ% s'% req) DistributionNotFound: ไม่มีการแจกแจงที่พบทั้งหมดสำหรับการใส่
Ashish Karpe

2

แน่นอนว่าคุณสามารถม้วนของคุณเองด้วยไลบรารีมาตรฐานที่มีอยู่ในทุกระดับตั้งแต่ซ็อกเก็ตจนถึงการปรับแต่ง urllib

http://pycurl.sourceforge.net/

"PyCurl เป็นอินเทอร์เฟซ Python สำหรับ libcurl"

"libcurl เป็นไลบรารีการโอนย้าย URL ฝั่งไคลเอ็นต์ที่ฟรีและใช้งานง่าย ... สนับสนุน ... HTTP PUT"

"ข้อเสียเปรียบหลักของ PycURL คือมันเป็นเลเยอร์บางที่สัมพันธ์กันกับ libcurl โดยไม่มีลำดับชั้นคลาส Pythonic ที่ดีนั่นหมายความว่ามันมีช่วงการเรียนรู้ที่ค่อนข้างชันเว้นแต่คุณจะคุ้นเคยกับ C API ของ libcurl แล้ว"


ฉันแน่ใจว่ามันจะทำงานได้ แต่ฉันต้องการบางสิ่งบางอย่างมากขึ้นเล็กน้อย
Rory

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.