อะไรคือความแตกต่างระหว่างโมดูล urllib, urllib2, urllib3 และคำขอ?


750

ในหลามสิ่งที่เป็นความแตกต่างระหว่างurllib, urllib2, urllib3และrequestsโมดูล? ทำไมถึงมีสาม? พวกเขาดูเหมือนจะทำสิ่งเดียวกัน ...


77
คำขอเป็นสิ่งที่ดีที่สุด
Yarin

2
ใช่ใช้คำขอ stackoverflow.com/questions/22676/…
hughdbrown

75
คำขอใช้ urllib3 .. 3 เป็นจำนวนที่มากกว่า
Bro

2
สรุป: ใช้requestsเวลาส่วนใหญ่ บางครั้งurllib2ทำงานได้ แต่ต้องใช้รหัสเพิ่มเติมและสง่างามน้อยลง urllibไม่ได้ใช้
เทรเวอร์บอยด์สมิ ธ

10
คำถามนี้ควรได้รับการอัปเดตเพื่อชี้แจงว่าurllibใน Python 3 เป็นอีกตัวเลือกหนึ่งให้ล้างออกด้วยวิธีต่างๆ แต่ขอบคุณเอกสารประกอบอย่างเป็นทางการยังตั้งข้อสังเกตว่า " แพ็คเกจขอแนะนำสำหรับส่วนต่อประสานไคลเอนต์ HTTP ระดับสูง " ที่21.6 urllib.request - ไลบรารีที่ขยายได้สำหรับการเปิด URL - เอกสาร Python 3.6.3
nealmcb

คำตอบ:


714

ฉันรู้ว่ามันถูกพูดไปแล้ว แต่ฉันขอแนะนำrequestsแพ็คเกจ Python

หากคุณใช้ภาษาอื่นนอกเหนือจากไพ ธ อนคุณอาจกำลังคิดurllibและurllib2ใช้งานง่ายไม่ใช้รหัสมากและมีความสามารถสูงนั่นคือสิ่งที่ฉันคิด แต่requestsแพ็คเกจมีประโยชน์อย่างไม่น่าเชื่อและสั้นมากที่ทุกคนควรใช้งาน

ก่อนอื่นจะรองรับ API ที่พักผ่อนอย่างสมบูรณ์และทำได้ง่ายเช่นเดียวกับ:

import requests

resp = requests.get('http://www.mywebsite.com/user')
resp = requests.post('http://www.mywebsite.com/user')
resp = requests.put('http://www.mywebsite.com/user/put')
resp = requests.delete('http://www.mywebsite.com/user/delete')

ไม่ว่า GET / POST คุณจะไม่ต้องเข้ารหัสพารามิเตอร์อีกต่อไป แต่จะใช้พจนานุกรมเป็นอาร์กิวเมนต์และทำได้ดี:

userdata = {"firstname": "John", "lastname": "Doe", "password": "jdoe123"}
resp = requests.post('http://www.mywebsite.com/user', data=userdata)

นอกจากนี้ยังมีตัวถอดรหัส JSON ในตัว (อีกครั้งฉันรู้ว่าjson.loads()การเขียนไม่มาก แต่แน่ใจว่าสะดวก):

resp.json()

หรือหากข้อมูลการตอบกลับของคุณเป็นเพียงข้อความให้ใช้:

resp.text

นี่เป็นเพียงส่วนยอดของภูเขาน้ำแข็ง นี่คือรายการของคุณสมบัติจากเว็บไซต์ร้องขอ:

  • โดเมนและ URL ระหว่างประเทศ
  • Keep-Alive & Connection Pooling
  • เซสชันที่มีการคงอยู่ของคุกกี้
  • การยืนยัน SSL แบบเบราว์เซอร์
  • การพิสูจน์ตัวตนพื้นฐาน / ข้อมูลสำคัญ
  • คุกกี้คีย์ / ค่า Elegant
  • การบีบอัดอัตโนมัติ
  • หน่วยตอบรับ Unicode
  • การอัพโหลดไฟล์หลายส่วน
  • หมดเวลาเชื่อมต่อ
  • .netrc สนับสนุน
  • รายการสินค้า
  • Python 2.6 —3.4
  • Thread ปลอดภัย

32
ฉันเลือกคำตอบนี้เป็นคำตอบเพราะคำตอบเดิมหมดไปแล้ว ดังนั้นหากคุณสงสัยว่าทำไมคำตอบนี้อยู่ข้างหน้าคำตอบด้วย 76 upvotes เพราะการร้องขอเป็นวิธี defacto ใหม่ในการทำสิ่งต่าง ๆ
Paul Biggar

132
@ PaulBiggar คุณบอกว่านี่เป็นคำตอบที่ดีที่สุด แต่มันไม่ได้ตอบคำถามจริงๆ ฉันมาที่นี่เพื่อค้นหาความแตกต่างระหว่าง urllib และ urllib2 โดยเฉพาะอย่างยิ่งเกี่ยวกับคุณสมบัติการเข้ารหัส URL คำตอบ: ใช้คำขอ! ;) เพียงแค่บอกว่าคุณอาจต้องการชี้แจงคำถาม คำตอบจาก Crast นั้นตอบคำถามได้อย่างสมบูรณ์แบบ
exhuma

2
มันจะช่วยให้ทราบว่าเอกสาร Python 3 มีอีกหนึ่งห้องสมุดที่แตกต่างกันurllibและเอกสารประกอบของมันยังบันทึกอย่างเป็นทางการว่า " แพคเกจคำขอขอแนะนำสำหรับส่วนต่อประสานไคลเอนต์ HTTP ระดับสูง " ที่21.6 urllib.request - ห้องสมุด Extensible สำหรับ URL ที่เปิด - งูหลามเอกสาร 3.6.3และเป็นห้องสมุดที่ดีใช้โดยurllib3 requests
nealmcb

ตกลงยกเว้นผมมีความประทับใจคำขอไม่มีทดแทนสำหรับurllib.parse()
บ๊อบสไตน์

ตกลง. ด้วย @PaulBiggar - คำขอดูเหมือนเป็นวิธีที่ไม่จริง ในความเป็นจริงฉันมาถึงที่นี่บนพื้นฐานที่ urllib (และรุ่นอื่น ๆ ) ไม่ทำงานหรือไม่ดีเมื่อเทียบกับคำขอ
DL

205

urllib2 มีฟังก์ชั่นพิเศษบางอย่างเช่นurlopen()ฟังก์ชั่นช่วยให้คุณสามารถระบุส่วนหัว (โดยปกติคุณจะต้องใช้ httplib ในอดีตซึ่งเป็น verbose ที่มากขึ้น) ที่สำคัญยิ่งกว่าแม้ว่า urllib2 จะให้Requestชั้นเรียนเพิ่มเติม วิธีการเปิดเผยในการทำคำขอ:

r = Request(url='http://www.mysite.com')
r.add_header('User-Agent', 'awesome fetcher')
r.add_data(urllib.urlencode({'foo': 'bar'})
response = urlopen(r)

โปรดทราบว่าurlencode()มีเฉพาะใน urllib ไม่ใช่ urllib2

นอกจากนี้ยังมีตัวจัดการสำหรับการใช้การสนับสนุน URL ขั้นสูงเพิ่มเติมใน urllib2 คำตอบสั้น ๆ คือหากคุณไม่ได้ทำงานกับรหัสดั้งเดิมคุณอาจต้องการใช้เครื่องมือเปิด URL จาก urllib2 แต่คุณยังต้องนำเข้าสู่ urllib สำหรับฟังก์ชันยูทิลิตี้บางอย่าง

คำตอบโบนัส ด้วย Google App Engine คุณสามารถใช้ httplib, urllib หรือ urllib2 ใด ๆ ก็ได้ แต่ทั้งหมดนี้เป็นเพียงคำแนะนำสำหรับ API การดึง URL ของ Google นั่นคือคุณยังคงมีข้อ จำกัด เช่นพอร์ตโปรโตคอลและความยาวของการตอบสนองที่ได้รับอนุญาต คุณสามารถใช้แกนหลักของไลบรารีได้ตามที่คุณคาดหวังว่าจะได้รับ URL HTTP


1
ใครบางคนสร้าง url ด้วยสตริงการสืบค้นที่เข้ารหัสโดยใช้ urllib2 มันเป็นเหตุผลเดียวที่ฉันใช้ urllib และฉันต้องการทำให้แน่ใจว่าฉันทำทุกอย่างด้วยวิธีที่ทันสมัยที่สุด
Gattster

2
เช่นเดียวกับในตัวอย่างข้างต้นของฉันคุณใช้urlopen()และRequestจากurllib2และคุณใช้urlencode()จากurllib ไม่มีอันตรายใด ๆ ในการใช้ทั้งสองไลบรารีตราบใดที่คุณตรวจสอบให้แน่ใจว่าคุณใช้ urlopen ที่ถูกต้อง [urllib docs] [1] มีความชัดเจนในการใช้สิ่งนี้คือการใช้งานที่ได้รับการยอมรับ [1]: docs.python.org/library/urllib2.html#urllib2.urlopen
Crast

ฉันใช้ส่วนสำคัญนี้เพื่อurllib2.urlopen; มีรูปแบบอื่น ๆ เช่นกัน
Andrei-Niculae Petre

urllib2 ไม่สนับสนุนการใส่หรือลบซึ่งเป็นความเจ็บปวด
fkl

1
requestsอนุญาตให้ส่วนหัวที่กำหนดเอง: docs.python-requests.org/en/master/user/quickstart/?hl=th
Omer Dagan

46

urllibและurllib2เป็นทั้งโมดูล Python ที่ทำหน้าที่ขอ URL ที่เกี่ยวข้อง แต่มีฟังก์ชั่นที่แตกต่างกัน

1) urllib2 สามารถยอมรับวัตถุคำขอเพื่อตั้งค่าส่วนหัวสำหรับคำขอ URL urllib ยอมรับเฉพาะ URL เท่านั้น

2) urllib ให้urlencodeวิธีการซึ่งใช้สำหรับการสร้างสตริงการสืบค้น GET, urllib2 ไม่มีฟังก์ชันดังกล่าว นี่คือหนึ่งในเหตุผลที่มักใช้ urllib ร่วมกับ urllib2

คำขอ - คำขอเป็นห้องสมุด HTTP ที่ใช้งานง่ายและง่ายต่อการเขียนใน Python

1) คำขอ Python เข้ารหัสพารามิเตอร์โดยอัตโนมัติเพื่อให้คุณส่งผ่านข้อโต้แย้งง่ายๆซึ่งไม่เหมือนกับในกรณีของ urllib ซึ่งคุณต้องใช้วิธีการurllib.encode ()เพื่อเข้ารหัสพารามิเตอร์ก่อนส่งต่อ

2) ถอดรหัสการตอบสนองเป็น Unicode โดยอัตโนมัติ

3) คำขอมีการจัดการข้อผิดพลาดที่สะดวกยิ่งขึ้นหากการรับรองความถูกต้องของคุณล้มเหลว urllib2 จะเพิ่ม urllib2.URLError ขณะที่คำขอจะส่งคืนออบเจ็กต์การตอบสนองตามปกติตามที่คาดไว้ ทั้งหมดที่คุณต้องดูว่าการร้องขอนั้นประสบความสำเร็จโดยบูลีนresponse.ok


10
แล้ว urllib3 ล่ะ?
PirateApp

1
@PirateApp ร้องขอถูกสร้างขึ้นที่ด้านบนของurllib3 ฉันคิดว่าโค้ดที่ใช้ urllib3 โดยตรงนั้นมีประสิทธิภาพมากกว่าเพราะช่วยให้คุณสามารถใช้เซสชั่นได้อีกครั้งในขณะที่คำขอ (อย่างน้อยก็ขอ 2, ที่ทุกคนใช้) สร้างหนึ่งสำหรับทุกคำขอ แต่ไม่อ้างถึงฉัน ไม่เป็นส่วนหนึ่งของไลบรารีมาตรฐาน ( ยัง )
Boris

12

ข้อแตกต่างที่สำคัญอย่างหนึ่งคือการย้ายพอร์ต Python2 ไปยัง Python3 urllib2 ไม่มีอยู่สำหรับ python3 และเมธอดที่ส่งไปยัง urllib ดังนั้นคุณกำลังใช้งานอย่างหนักและต้องการย้ายไปยัง Python3 ในอนาคตพิจารณาใช้ urllib อย่างไรก็ตามเครื่องมือ 2to3 จะทำงานให้คุณโดยอัตโนมัติ


12

เพียงเพื่อเพิ่มไปยังคำตอบที่มีอยู่ฉันไม่เห็นใครพูดถึงว่าการร้องขอหลามไม่ใช่ห้องสมุดท้องถิ่น หากคุณตกลงกับการเพิ่มการอ้างอิงจากนั้นคำขอก็ไม่เป็นไร อย่างไรก็ตามหากคุณพยายามหลีกเลี่ยงการเพิ่มการพึ่งพา urllib เป็นไลบรารี่แบบเนทีฟที่คุณมีอยู่แล้ว


11

ผมชอบฟังก์ชั่นและมันจะไม่ปรากฏอยู่ในurllib.urlencodeurllib2

>>> urllib.urlencode({'abc':'d f', 'def': '-!2'})
'abc=d+f&def=-%212'

4
แค่โน้ตให้ระวังด้วย urlencode เพราะมันไม่สามารถจัดการวัตถุ <unicode> โดยตรง - คุณต้องเข้ารหัสก่อนที่จะส่งไปยัง urlencode (u'blá'.encode ('utf-8') หรืออะไรก็ตาม)

@ user18015: ฉันไม่คิดว่านี่จะใช้กับ Python 3 คุณช่วยอธิบายได้ไหม?
Janus Troelsen

ดังที่ฉันได้กล่าวไว้ข้างต้นคำถามนี้และคำตอบต่าง ๆ ควรได้รับการอัพเดตเพื่อให้ชัดเจนว่าurllibใน Python 3 นั้นเป็นอีกตัวเลือกหนึ่ง แต่ขอบคุณเอกสารประกอบอย่างเป็นทางการยังตั้งข้อสังเกตว่า " แพ็คเกจขอแนะนำสำหรับส่วนต่อประสานไคลเอนต์ HTTP ระดับสูง " ที่21.6 urllib.request - ไลบรารีที่ขยายได้สำหรับการเปิด URL - เอกสาร Python 3.6.3
nealmcb

urllib2 ไม่มีอยู่ใน Python 3
Boris

7

ในการรับเนื้อหาของ URL:

try: # Try importing requests first.
    import requests
except ImportError: 
    try: # Try importing Python3 urllib
        import urllib.request
    except AttributeError: # Now importing Python2 urllib
        import urllib


def get_content(url):
    try:  # Using requests.
        return requests.get(url).content # Returns requests.models.Response.
    except NameError:  
        try: # Using Python3 urllib.
            with urllib.request.urlopen(index_url) as response:
                return response.read() # Returns http.client.HTTPResponse.
        except AttributeError: # Using Python3 urllib.
            return urllib.urlopen(url).read() # Returns an instance.

เป็นการยากที่จะเขียน Python2 และ Python3 และrequestโค้ดการพึ่งพาสำหรับการตอบสนองเพราะurlopen()ฟังก์ชั่นและrequests.get()ฟังก์ชั่นการคืนค่าประเภทที่แตกต่างกัน:

  • Python2 urllib.request.urlopen()ส่งคืน ahttp.client.HTTPResponse
  • Python3 urllib.urlopen(url)ส่งคืน aninstance
  • การร้องขอrequest.get(url)ส่งคืนrequests.models.Response

5

โดยทั่วไปคุณควรใช้ urllib2 เนื่องจากจะทำให้บางครั้งง่ายขึ้นเล็กน้อยโดยการยอมรับคำขอวัตถุและจะเพิ่ม URLException จากข้อผิดพลาดของโปรโตคอลด้วย ด้วย Google App Engine คุณไม่สามารถใช้งานได้ คุณต้องใช้URL Fetch APIที่ Google จัดเตรียมไว้ในสภาพแวดล้อม Python แบบ sandboxed


2
สิ่งที่คุณพูดเกี่ยวกับแอปพลิเคชั่นนั้นไม่เป็นความจริงทั้งหมด ตอนนี้คุณสามารถใช้ httplib, urllib และ urllib2 ใน App Engine ได้แล้วในตอนนี้ (เป็นโปรแกรมเสริมสำหรับดึงข้อมูล url ทำเพื่อให้โค้ดเพิ่มเติมเข้ากันได้กับ appengine)
Crast

อาจะต้องใหม่ รหัสของฉันล้มเหลวครั้งล่าสุดที่ฉันพยายามและต้องถูกเขียนใหม่เพื่อทำงานกับการดึงข้อมูล ...
Chinmay Kanchi


urllib2 ไม่มีอยู่ใน Python 3
Boris

@Boris มันอพยพไปurllib.requestและurllib.error
อลัน

1

จุดสำคัญที่ผมพบที่ขาดหายไปในคำตอบดังกล่าวคือผลตอบแทน urllib วัตถุของการพิมพ์<class http.client.HTTPResponse>ในขณะที่ผลตอบแทนrequests<class 'requests.models.Response'>

เนื่องจากนี้อ่าน () วิธีการที่สามารถใช้กับแต่ไม่ได้มีurllibrequests

PS: requestsมีอยู่มากมายด้วยวิธีการมากมายที่แทบจะไม่ต้องการอีกต่อไปเช่นread()>>

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