Jak przekonwertować słownik na ciąg zapytania w Pythonie?

Odpowiedzi:

158

Python 3

urllib.parse.urlencode(zapytanie, dawkaq = False, [...])

Konwertuj obiekt mapowania lub sekwencję krotek dwuelementowych, które mogą zawierać obiekty str lub bajty, na ciąg tekstowy ASCII zakodowany w procentach.

- Pythonie 3 urllib.parseDokumenty

A dictto odwzorowanie.

Starsza wersja Pythona

urllib.urlencode( query[, doseq])
Konwertuj obiekt mapujący lub sekwencję krotek dwuelementowych na łańcuch „zakodowany w procentach” ... ciąg key=valuepar oddzielonych '&'znakami ...

- Pythona 2,7 urllibDokumenty

Ignacio Vazquez-Abrams
źródło
1
To prawda, ale dictzwracane przez cgi.parse_qs()faktycznie ma lists jako swoje „wartości”. Przekazywanie ich bezpośrednio spowoduje powstanie bardzo dziwnie wyglądających ciągów zapytań.
Johnsyweb
To prawda. To nauczy mnie czytać więcej niż pierwsze zdanie!
Johnsyweb
18
urllib.parse.urlencode w Pythonie 3.
Denilson Sá Maia
Problem polega na tym, że urlencode zamieni spację na +, co nie jest zalecane.
user1633272
1
@ user1633272: Niezalecane według kogo?
Ignacio Vazquez-Abrams
67

W python3 nieco inaczej:

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

wynik: 'pram1=foo&param2=bar'

aby uzyskać zgodność z python2 i python3, wypróbuj to:

try:
    #python2
    from urllib import urlencode
except ImportError:
    #python3
    from urllib.parse import urlencode
Johnny Zhao
źródło
7

Szukasz czegoś dokładnie takiego urllib.urlencode()!

Jednak w przypadku wywołania parse_qs()(odróżnienia od parse_qsl()) klucze słownika są unikatowymi nazwami zmiennych zapytania, a wartości są listami wartości dla każdej nazwy.

Aby przekazać te informacje do urllib.urlencode(), musisz „spłaszczyć” te listy. Oto, jak możesz to zrobić za pomocą listy obejmującej krotki:

query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)
Johnsyweb
źródło
16
Albo możesz przejść doseq=True.
Ignacio Vazquez-Abrams
@downvoter: Jak mogę poprawić tę odpowiedź? Minęło sześć lat, odkąd to napisałem!
Johnsyweb
-1

Może szukasz czegoś takiego:

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

Pobiera słownik i konwertuje go na ciąg zapytania, podobnie jak urlencode. Doda końcowe „&” do ciągu zapytania, ale return query[:-1]naprawia to, jeśli jest to problem.

garbados
źródło
4
Czy już się spotkałeś str.join()? A co powiesz urllib.quote_plus()?
Ignacio Vazquez-Abrams
1
@garbados Twoje rozwiązanie powinno działać w prostych przypadkach. Jednak spojrzeć urlencodew urllib.py(powinien by w Pythonie zainstalować), aby zobaczyć, dlaczego tworząc łańcuch zapytania czasami nie jest tak proste, jak sugeruje odpowiedź (w szczególności potrzebę „cytat” pewne znaki, które nie są ważne w URL). @Ignacio odwołał się również do dwóch funkcji, które oczyściłyby twoją implementację i poprawiły ją.
Anthony Cramp
Ach, rzeczywiście. Przepraszamy za prymitywną implementację. Pokazuje, że powinienem być bardziej ostrożny, odpowiadając na pytania, z którymi sam nigdy się nie spotkałem.
garbados
Chociaż może to nie być najlepsza odpowiedź, dokładnie to chciałem zobaczyć, klikając tytuł tego pytania. Mam tylko 4 elementy w dictwie, które muszę zamienić w parę nazwa = wartość oddzieloną znakiem „&”. Moje wartości są kontrolowane. Str.join () jest przydatna w moim przypadku, ale znowu nie potrzebuję quote_plus (), ponieważ nie jest to kod dostępny publicznie :) Dzięki!
harperville,
1
@harperville, ale bardziej poprawny sposób ( from urllib.parse import urlencode; urlencode(your_dict)) jest krótszy i łatwiejszy niż ten! Przyznam, że czasem mądrze jest wymyślić na nowo koło, nawet tandetnie, gdy dostęp do istniejących, dobrze zaprojektowanych kół jest drogi lub niewygodny, ale tutaj użycie gotowego koła jest łatwiejsze i szybsze niż toczenie własnego, gorszego .
Mark Amery,