¿Cómo convertir un diccionario a una cadena de consulta en Python?

Respuestas:

158

Python 3

urllib.parse.urlencode(consulta, doseq = False, [...])

Convierta un objeto de mapeo o una secuencia de tuplas de dos elementos, que pueden contener objetos str o bytes, en una cadena de texto ASCII codificada en porcentaje.

- Python 3 urllib.parsedocs

A dictes un mapeo.

Python heredado

urllib.urlencode( query[, doseq])
Convertir un objeto de mapeo o una secuencia de tuplas de dos elementos en una cadena de "porcentaje codificado" ... una serie de key=valuepares separados por '&'caracteres ...

- Python 2.7 urllibdocs

Ignacio Vázquez-Abrams
fuente
1
Esto es cierto, pero el dictdevuelto por en cgi.parse_qs()realidad tiene lists como sus "valores". Pasar estos directamente dará como resultado cadenas de consulta de aspecto muy extraño.
Johnsyweb
Suficientemente cierto. ¡Eso me enseñará a leer más que la primera oración!
Johnsyweb
18
urllib.parse.urlencode en Python 3.
Denilson Sá Maia
El problema es que urlencode convertirá el espacio en +, lo cual no se recomienda.
user1633272
1
@ user1633272: ¿No recomendado según quién?
Ignacio Vazquez-Abrams
65

En python3, ligeramente diferente:

from urllib.parse import urlencode
urlencode({'pram1': 'foo', 'param2': 'bar'})

salida: 'pram1=foo&param2=bar'

para compatibilidad con python2 y python3, intente esto:

try:
    #python2
    from urllib import urlencode
except ImportError:
    #python3
    from urllib.parse import urlencode
Johnny Zhao
fuente
6

¡Estás buscando algo exactamente igual urllib.urlencode()!

Sin embargo, cuando llama parse_qs()(distinto de parse_qsl()), las claves del diccionario son los nombres únicos de las variables de consulta y los valores son listas de valores para cada nombre.

Para pasar esta información urllib.urlencode(), debe "aplanar" estas listas. Así es como puede hacerlo con una lista de comprensión de tuplas:

query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)
Johnsyweb
fuente
15
O podrías pasar doseq=True.
Ignacio Vazquez-Abrams
@downvoter: ¿Cómo podría mejorar esta respuesta? ¡Han pasado seis años desde que lo escribí!
Johnsyweb
-1

Quizás estés buscando algo como esto:

def dictToQuery(d):
  query = ''
  for key in d.keys():
    query += str(key) + '=' + str(d[key]) + "&"
  return query

Toma un diccionario y lo convierte en una cadena de consulta, como urlencode. Agregará un "&" final a la cadena de consulta, pero lo return query[:-1]corrige si es un problema.

garbados
fuente
4
¿Ya te conociste str.join()? ¿Qué tal urllib.quote_plus()?
Ignacio Vazquez-Abrams
1
@garbados Su solución debería funcionar en casos simples. Sin embargo, tener una mirada urlencodeen urllib.py(debe por su pitón en la instalación) para ver qué crear una cadena de consulta a veces no es tan simple como su respuesta implica (en particular, la necesidad de 'cita' ciertos caracteres que no son válidos en una URL). @Ignacio también ha hecho referencia a dos funciones que limpiarían su implementación y la corregirían.
Anthony Cramp
Ah, en verdad. Perdón por la mala implementación. Va a demostrar que debería ser más cuidadoso al responder preguntas a las que nunca me he enfrentado.
garbados
Si bien esta puede no ser la mejor respuesta, es exactamente lo que quería ver cuando hice clic en el título de esta pregunta. Solo tengo 4 elementos en un dictado que necesito convertir en un par nombre = valor separados por un '&'. Mis valores están controlados. El str.join () es útil en mi caso, pero no necesito quote_plus (), nuevamente, porque no es un código público :) ¡Gracias!
harperville
1
@harperville, ¡pero la forma más correcta ( from urllib.parse import urlencode; urlencode(your_dict)) es más corta y más fácil que esta! Reconozco que a veces es inteligente reinventar la rueda, incluso aunque sea de mala calidad, cuando es caro o inconveniente acceder a las ruedas existentes y bien diseñadas, pero aquí usar la rueda estándar es más fácil y rápido que hacer rodar una rueda inferior. .
Mark Amery