¿Cuáles son las diferencias entre urllib, urllib2, urllib3 y el módulo de solicitudes?

751

En Python, ¿cuáles son las diferencias entre los urllib, urllib2, urllib3y requestslos módulos? ¿Por qué hay tres? Parecen hacer lo mismo ...

Paul Biggar
fuente
78
Solicitudes es lo mejor.
Yarin
2
Sí, usa solicitudes. stackoverflow.com/questions/22676/…
hughdbrown
76
solicitudes utiliza urllib3 .. 3 es un número mayor
Bro
2
resumen: uso la requestsmayor parte del tiempo. a veces urllib2funciona pero requiere más código y es menos elegante. no utilice urllib.
Trevor Boyd Smith
10
Esta pregunta debe actualizarse para aclarar que urlliben Python 3 hay otra opción, limpiada de varias maneras. Pero, afortunadamente, la documentación oficial también señala que " el paquete Solicitudes se recomienda para una interfaz de cliente HTTP de nivel superior " en 21.6. urllib.request - Biblioteca extensible para abrir URL - Documentación de Python 3.6.3
nealmcb

Respuestas:

714

Sé que ya se ha dicho, pero recomiendo encarecidamente el requestspaquete Python.

Si ha usado otros lenguajes que no sean python, probablemente esté pensando urlliby urllib2sea ​​fácil de usar, no tenga mucho código y sea altamente capaz, así es como solía pensar. Pero el requestspaquete es tan increíblemente útil y breve que todos deberían usarlo.

Primero, es compatible con una API totalmente relajante y es tan fácil como:

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')

Independientemente de si GET / POST, nunca tendrá que codificar parámetros nuevamente, simplemente toma un diccionario como argumento y está listo para comenzar:

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

Además, incluso tiene un decodificador JSON incorporado (de nuevo, sé json.loads()que no es mucho más que escribir, pero esto es conveniente):

resp.json()

O si sus datos de respuesta son solo texto, use:

resp.text

Esto es sólo la punta del iceberg. Esta es la lista de características del sitio de solicitudes:

  • Dominios y URL internacionales
  • Mantener vivo y agrupación de conexiones
  • Sesiones con persistencia de cookies
  • Verificación SSL estilo navegador
  • Autenticación Básica / Digestiva
  • Cookies elegantes de clave / valor
  • Descompresión automática
  • Cuerpos de respuesta Unicode
  • Subidas de archivos de varias partes
  • Tiempos de espera de conexión
  • soporte .netrc
  • Elemento de la lista
  • Python 2.6—3.4
  • A salvo de amenazas.
Conejera
fuente
32
Elegí esto como la respuesta porque la respuesta original se ha vuelto obsoleta. Entonces, si se pregunta por qué esta respuesta está por delante de una respuesta con 76 votos a favor, es porque Solicitudes es la nueva forma de facto de hacer las cosas.
Paul Biggar
132
@PaulBiggar, dices que esta es la mejor respuesta. Pero en realidad no responde la pregunta. Vine aquí para descubrir las diferencias entre urllib y urllib2. Especialmente sobre las características de codificación de URL. La respuesta: ¡usa solicitudes! ;) Solo digo que es posible que desee aclarar la pregunta. Tal como está, la respuesta de Crast en realidad responde a la pregunta perfectamente.
exhuma
2
Sería útil tener en cuenta que la documentación de Python 3 tiene otra biblioteca distinta urlliby que su documentación también señala oficialmente que " el paquete de solicitudes se recomienda para una interfaz de cliente HTTP de nivel superior " en 21.6. urllib.request - Biblioteca extensible para abrir URLs - Documentación de Python 3.6.3 , y esa urllib3es una gran biblioteca utilizada por requests.
nealmcb
Bien, excepto que tengo la impresión de petición tiene ningún reemplazo paraurllib.parse()
Bob Stein
de acuerdo. con @PaulBiggar: las solicitudes parecen ser de facto. De hecho, llegué aquí porque urllib (y otras versiones) no funcionan o son subóptimas en comparación con las solicitudes.
DL
205

urllib2 proporciona alguna funcionalidad adicional, es decir, la urlopen()función puede permitirle especificar encabezados (normalmente habría tenido que usar httplib en el pasado, que es mucho más detallado). Sin embargo, lo más importante es que urllib2 proporciona la Requestclase, que permite enfoque declarativo para hacer una solicitud:

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

Tenga en cuenta que urlencode()solo está en urllib, no en urllib2.

También hay controladores para implementar un soporte de URL más avanzado en urllib2. La respuesta breve es que, a menos que esté trabajando con código heredado, probablemente quiera usar el abridor de URL de urllib2, pero aún necesita importar a urllib para algunas de las funciones de utilidad.

Respuesta adicional Con Google App Engine, puede usar cualquiera de httplib, urllib o urllib2, pero todos ellos son solo envoltorios para la API URL Fetch de Google. Es decir, aún está sujeto a las mismas limitaciones, como puertos, protocolos y la duración de la respuesta permitida. Sin embargo, puede usar el núcleo de las bibliotecas como esperaría para recuperar URL HTTP.

Crast
fuente
1
¿Cómo alguien crea una url con una cadena de consulta codificada usando urllib2? Es la única razón por la que estoy usando urllib y me gustaría asegurarme de que estoy haciendo todo de la mejor manera.
Gattster
2
Como en mi ejemplo anterior, usas urlopen()y Requestdesde urllib2 , y usas urlencode()desde urllib . No hay daño real en el uso de ambas bibliotecas, siempre y cuando se asegure de usar el urlopen correcto. Los [urllib docs] [1] tienen claro que usar esto es un uso aceptado. [1]: docs.python.org/library/urllib2.html#urllib2.urlopen
Crast
He utilizado este quid de urllib2.urlopen; contiene otras variaciones también.
Andrei-Niculae Petre
urllib2 no admite poner o eliminar, lo cual es un dolor
fkl
2
requeststambién permite encabezados personalizados: docs.python-requests.org/en/master/user/quickstart/…
Omer Dagan
46

urllib y urllib2 son módulos de Python que hacen cosas relacionadas con la solicitud de URL pero ofrecen diferentes funcionalidades.

1) urllib2 puede aceptar un objeto Request para configurar los encabezados de una solicitud de URL, urllib acepta solo una URL.

2) urllib proporciona el método urlencode que se utiliza para la generación de cadenas de consulta GET, urllib2 no tiene esa función. Esta es una de las razones por las que a menudo se usa urllib junto con urllib2.

Solicitudes : las solicitudes son una biblioteca HTTP simple y fácil de usar escrita en Python.

1) Python Requests codifica los parámetros automáticamente, por lo que solo debe pasarlos como argumentos simples, a diferencia del caso de urllib, donde debe usar el método urllib.encode () para codificar los parámetros antes de pasarlos.

2) Decodificó automáticamente la respuesta en Unicode.

3) Las solicitudes también tienen un manejo de errores mucho más conveniente. Si su autenticación falla, urllib2 generará un error urllib2.URLE, mientras que Solicitudes devolverá un objeto de respuesta normal, como se esperaba. Todo lo que tiene que ver si la solicitud fue exitosa por boolean response.ok

Siyaram Malav
fuente
10
¿Qué hay de urllib3?
PirateApp
1
Las solicitudes de @PirateApp se crean sobre urllib3 . Creo que el código que usa urllib3 directamente puede ser más eficiente, porque le permite reutilizar la sesión, mientras que las solicitudes (al menos las solicitudes 2, la que todos usan) crean una para cada solicitud, pero no me cite al respecto. Ninguno de los dos es parte de la biblioteca estándar ( todavía )
Boris
12

Una diferencia considerable es portar Python2 a Python3. urllib2 no existe para python3 y sus métodos portados a urllib. Por lo tanto, lo está utilizando mucho y desea migrar a Python3 en el futuro, considere usar urllib. Sin embargo, la herramienta 2to3 hará automáticamente la mayor parte del trabajo por usted.

Arash
fuente
12

Solo para agregar a las respuestas existentes, no veo que nadie mencione que las solicitudes de Python no son una biblioteca nativa. Si está de acuerdo con agregar dependencias, entonces las solicitudes están bien. Sin embargo, si está intentando evitar agregar dependencias, urllib es una biblioteca nativa de Python que ya está disponible para usted.

Zeitgeist
fuente
11

Me gusta la urllib.urlencodefunción, y no parece existir en urllib2.

>>> urllib.urlencode({'abc':'d f', 'def': '-!2'})
'abc=d+f&def=-%212'
Gattster
fuente
44
Solo una nota, tenga cuidado con urlencode ya que no puede manejar objetos <unicode> directamente; debe codificarlos antes de enviarlos a urlencode (u'blá'.encode ('utf-8'), o lo que sea).
@ user18015: No creo que esto se aplique a Python 3, ¿puede aclararlo?
Janus Troelsen
Como señalé anteriormente, esta pregunta y las diversas respuestas deben actualizarse para aclarar que urlliben Python 3 es otra opción, limpiada de varias maneras. Pero afortunadamente, la documentación oficial también señala que " el paquete de solicitudes se recomienda para una interfaz de cliente HTTP de nivel superior " en 21.6. urllib.request - Biblioteca extensible para abrir URL - Documentación de Python 3.6.3
nealmcb
urllib2 no existe en absoluto en Python 3
Boris
7

Para obtener el contenido de una 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.

Es difícil escribir Python2 y Python3 y el requestcódigo de dependencias para las respuestas porque sus urlopen()funciones y requests.get()funciones devuelven diferentes tipos:

  • Python2 urllib.request.urlopen()devuelve unhttp.client.HTTPResponse
  • Python3 urllib.urlopen(url)devuelve uninstance
  • Solicitud request.get(url) devuelve unrequests.models.Response
alvas
fuente
5

En general, debe usar urllib2, ya que esto hace las cosas un poco más fáciles a veces al aceptar objetos de solicitud y también generará una excepción URLE en los errores de protocolo. Sin embargo, con Google App Engine, tampoco puedes usarlo. Debe utilizar la API de obtención de URL que proporciona Google en su entorno de Python de espacio aislado.

Chinmay Kanchi
fuente
2
Lo que dijiste sobre appengine no es del todo cierto. En realidad, puede usar httplib, urllib y urllib2 en App Engine ahora (son envoltorios para la búsqueda de URL, hecho para que más código sea compatible con appengine).
Crast
Ah, debe ser nuevo. Mi código falló la última vez que lo intenté y tuve que reescribirlo para trabajar con fetch ...
Chinmay Kanchi
urllib2 no existe en absoluto en Python 3
Boris
@ Boris Migró a urllib.request y urllib.error .
Alan
1

Un punto clave que me parece que falta en las respuestas anteriores es que urllib devuelve un objeto de tipo <class http.client.HTTPResponse>mientras que requestsdevuelve<class 'requests.models.Response'> .

Debido a esto, el método read () se puede usar con urllibpero no conrequests .

PD: requestsya es rico en tantos métodos que apenas necesita uno más como read();>

paradoxlover
fuente