¿Cómo codificar en porcentaje los parámetros de URL en Python?

Si lo hago

url = "http://example.com?p=" + urllib.quote(query) 
  1. No codifica / a %2F (rompe la normalización de OAuth)
  2. No maneja Unicode (lanza una excepción)

¿Hay una mejor biblioteca?

De los documentos :

 urllib.quote(string[, safe]) 

Reemplace los caracteres especiales en la cadena usando el escape% xx. Las letras, los dígitos y los caracteres ‘_.-‘ nunca se citan. De forma predeterminada, esta función está diseñada para citar la sección de ruta de la URL. El parámetro seguro opcional especifica caracteres adicionales que no deben citarse; su valor predeterminado es ‘/’

Eso significa que pasar “” de forma segura resolverá tu primer problema:

 >>> urllib.quote('/test') '/test' >>> urllib.quote('/test', safe='') '%2Ftest' 

Sobre el segundo tema, hay un informe de error al respecto aquí . Aparentemente, se solucionó en Python 3. Puedes solucionarlo codificando como utf8 de esta manera:

 >>> query = urllib.quote(u"Müller".encode('utf8')) >>> print urllib.unquote(query).decode('utf8') Müller 

Por cierto echar un vistazo a urlencode

Tenga en cuenta que urllib.quote movió a urllib.parse.quote en Python3

En Python 3, urllib.quote se ha movido a urllib.parse.quote y maneja Unicode de forma predeterminada.

 >>> from urllib.parse import quote >>> quote('/test') '/test' >>> quote('/test', safe='') '%2Ftest' >>> quote('/El Niño/') '/El%20Ni%C3%B1o/' 

Mi respuesta es similar a la de Paolo.

Creo que las requests módulos son mucho mejores. Está basado en urllib3 . Puedes probar esto:

 >>> from requests.utils import quote >>> quote('/test') '/test' >>> quote('/test', safe='') '%2Ftest' 

Si estás usando django, puedes usar urlquote:

 >>> from django.utils.http import urlquote >>> urlquote(u"Müller") u'M%C3%BCller' 

Tenga en cuenta que los cambios en Python desde que se publicó esta respuesta significan que ahora es un contenedor heredado. Desde el código fuente de Django 2.1 para django.utils.http:

 A legacy compatibility wrapper to Python's urllib.parse.quote() function. (was used for unicode handling on Python 2) 

Es mejor utilizar urlencode aquí. No hay mucha diferencia para un solo parámetro, pero en mi humilde opinión el código es más claro. (¡Parece confuso ver una función quote_plus ! Especialmente las que vienen de otros idiomas)

 In [21]: query='lskdfj/sdfkjdf/ksdfj skfj' In [22]: val=34 In [23]: from urllib.parse import urlencode In [24]: encoded = urlencode(dict(p=query,val=val)) In [25]: print(f"http://example.com?{encoded}") http://example.com?p=lskdfj%2Fsdfkjdf%2Fksdfj+skfj&val=34 

Docs

urlencode: https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlencode

quote_plus: https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote_plus