Como converter um dicionário em string de consulta em Python?


Respostas:


158

Python 3

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

Converta um objeto de mapeamento ou uma sequência de tuplas de dois elementos, que pode conter objetos str ou bytes, em uma string de texto ASCII com codificação percentual.

- documentos Python 3urllib.parse

A dicté um mapeamento.

Python legado

urllib.urlencode( query[, doseq])
Converta um objeto de mapeamento ou uma sequência de tuplas de dois elementos em uma string "codificada em porcentagem" ... uma série de key=valuepares separados por '&'caracteres ...

- documentos Python 2.7urllib


1
Isso é verdade, mas o dictretornado por cgi.parse_qs()realmente tem lists como seus "valores". Passá-los diretamente resultará em strings de consulta de aparência muito estranha.
Johnsyweb de

É verdade. Isso vai me ensinar a ler mais do que a primeira frase!
Johnsyweb


O problema é que o urlencode converterá o espaço em +, o que não é recomendado.
user1633272

1
@ user1633272: Não recomendado de acordo com quem?
Ignacio Vazquez-Abrams

65

Em python3, ligeiramente diferente:

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

resultado: 'pram1=foo&param2=bar'

para compatibilidade com python2 e python3, tente o seguinte:

try:
    #python2
    from urllib import urlencode
except ImportError:
    #python3
    from urllib.parse import urlencode

6

Você está procurando por algo exatamente igual urllib.urlencode()!

No entanto, quando você chama parse_qs()(diferente de parse_qsl()), as chaves de dicionário são os nomes de variáveis ​​de consulta exclusivos e os valores são listas de valores para cada nome.

Para passar essas informações urllib.urlencode(), você deve "nivelar" essas listas. Aqui está como você pode fazer isso com uma compreensão de lista de tuplas:

query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)

15
Ou você pode passar doseq=True.
Ignacio Vazquez-Abrams,

@downvoter: Como posso melhorar essa resposta? Já se passaram seis anos desde que o escrevi!
Johnsyweb

-1

Talvez você esteja procurando algo assim:

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

Ele pega um dicionário e o converte em uma string de consulta, assim como o urlencode. Ele acrescentará um "&" final à string de consulta, mas return query[:-1]corrigirá isso, se for um problema.


4
Você já se conheceu str.join()? Que tal urllib.quote_plus()?
Ignacio Vazquez-Abrams,

1
@garbados Sua solução deve funcionar em casos simples. No entanto, ter um olhar urlencodeem urllib.py(ele deve por em sua Python instalar) para ver por que a criação de uma cadeia de consulta, por vezes, não é tão simples como a sua resposta implica (em particular a necessidade de 'citação' determinados caracteres que não são válidas em um URL). @Ignacio também fez referência a duas funções que limpariam sua implementação e a tornariam correta.
Anthony Cramp,

Ah, é verdade. Desculpe pela implementação tosca. Isso mostra que devo ser mais cuidadoso ao responder a perguntas que nunca enfrentei.
garbados de

Embora essa possa não ser a melhor resposta, é exatamente o que eu queria ver ao clicar no título desta pergunta. Eu tenho apenas 4 itens em um dicionário que preciso transformar em um par nome = valor separado por um '&'. Meus valores são controlados. O str.join () é útil no meu caso, mas não preciso de quote_plus (), novamente, porque não é um código voltado ao público :) Obrigado!
Harperville

1
@harperville mas a forma mais correta ( from urllib.parse import urlencode; urlencode(your_dict)) é mais curta e fácil do que esta! Admito que às vezes é inteligente reinventar a roda, mesmo de maneira inadequada, quando é caro ou inconveniente acessar as rodas existentes e bem projetadas, mas aqui usar a roda pronta é mais fácil e rápido do que girar a roda inferior .
Mark Amery
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.