Come convertire un dizionario in una stringa di query in Python?


Risposte:


158

Python 3

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

Converte un oggetto di mappatura o una sequenza di tuple a due elementi, che possono contenere oggetti str o byte, in una stringa di testo ASCII con codifica percentuale.

- Documenti di Python 3urllib.parse

A dictè una mappatura.

Legacy Python

urllib.urlencode( query[, doseq])
Converti un oggetto di mappatura o una sequenza di tuple di due elementi in una stringa "codificata in percentuale" ... una serie di key=valuecoppie separate da '&'caratteri ...

- Documenti Python 2.7urllib


1
Questo è vero, ma il valore dictrestituito da cgi.parse_qs()ha effettivamente lists come "valori". Il passaggio di questi direttamente risulterà in stringhe di query dall'aspetto molto strano.
Johnsyweb

Abbastanza vero. Questo mi insegnerà a leggere più della prima frase!
Johnsyweb


Il problema è che urlencode convertirà lo spazio in +, il che non è consigliato.
user1633272

1
@ user1633272: Non consigliato secondo chi?
Ignacio Vazquez-Abrams

65

In python3, leggermente diverso:

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

produzione: 'pram1=foo&param2=bar'

per la compatibilità con python2 e python3, prova questo:

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

6

Stai cercando qualcosa esattamente come urllib.urlencode()!

Tuttavia, quando si chiama parse_qs()(distinto da parse_qsl()), le chiavi del dizionario sono i nomi delle variabili di query univoci ei valori sono elenchi di valori per ogni nome.

Per passare queste informazioni urllib.urlencode(), è necessario "appiattire" questi elenchi. Ecco come puoi farlo con una lista di comprensione di tuple:

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

15
Oppure potresti passare doseq=True.
Ignacio Vazquez-Abrams

@downvoter: come potrei migliorare questa risposta? Sono passati sei anni da quando l'ho scritto!
Johnsyweb

-1

Forse stai cercando qualcosa del genere:

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

Prende un dizionario e lo converte in una stringa di query, proprio come urlencode. Aggiungerà un "&" finale alla stringa di query, ma lo return query[:-1]risolverà, se si tratta di un problema.


4
Ti sei già incontrato str.join()? Che ne dici urllib.quote_plus()?
Ignacio Vazquez-Abrams

1
@garbados La tua soluzione dovrebbe funzionare in casi semplici. Tuttavia, date un'occhiata urlencodea urllib.py(dovrebbe da nel vostro Python installazione) per vedere il motivo per cui la creazione di una stringa di query a volte non è così semplice come la risposta implica (in particolare la necessità di 'quote' certi caratteri che non sono validi in un URL). @Ignacio ha anche fatto riferimento a due funzioni che ripulirebbero la tua implementazione e la renderebbero corretta.
Anthony Cramp

Ah, davvero. Ci scusiamo per l'implementazione rozza. Questo dimostra che dovrei essere più attento a rispondere alle domande che non ho mai affrontato.
Garbados

Anche se questa potrebbe non essere la risposta migliore, è esattamente quello che volevo vedere quando ho fatto clic sul titolo di questa domanda. Ho solo 4 elementi in un dict che devo trasformare in una coppia nome = valore separata da una "&". I miei valori sono controllati. La str.join () è utile nel mio caso ma non ho bisogno di quote_plus (), ancora una volta, perché non è codice pubblico :) Grazie!
Harperville

1
@harperville ma il modo più corretto ( from urllib.parse import urlencode; urlencode(your_dict)) è più breve e più facile di questo! Concedo che a volte è intelligente reinventare la ruota, anche in modo scadente, quando è costoso o scomodo accedere a ruote esistenti e ben progettate, ma qui usare la ruota standard è più facile e veloce che far rotolare la tua ruota inferiore .
Mark Amery
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.