95

I have tried to follow the documentation but was not able to use urlparse.parse.quote_plus() in Python 3:

from urllib.parse import urlparse

params = urlparse.parse.quote_plus({'username': 'administrator', 'password': 'xyz'})

I get

AttributeError: 'function' object has no attribute 'parse'

amphibient
  • 29,770
  • 54
  • 146
  • 240

3 Answers3

135

You misread the documentation. You need to do two things:

  1. Quote each key and value from your dictionary, and
  2. Encode those into a URL

Luckily urllib.parse.urlencode does both those things in a single step, and that's the function you should be using.

from urllib.parse import urlencode, quote_plus

payload = {'username':'administrator', 'password':'xyz'}
result = urlencode(payload, quote_via=quote_plus)
# 'password=xyz&username=administrator'
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • 2
    It's a pity that it does not work with plain strings like PHP's function `urlencode()`. So one must have key:value pairs, which IMHO is too restrictive. For instance, I have a need to URL encode only a part of string - password in `proto://user:pass@site.com` cmd line to run duplicity backup. Python2 does work as intended though: `python2 -c "import urllib as ul; print ul.quote_plus('$KEY');"` -> where `$KEY` is supplied from bash script. – stamster Sep 29 '18 at 09:14
  • 10
    @stamster `quote_plus` is available in Python 3 the same way. `python3 -c "import urllib.parse as ul; print(ul.quote_plus('$KEY'))"` – Adam Smith Sep 29 '18 at 20:44
96

For Python 3 you could try using quote instead of quote_plus:

import urllib.parse

print(urllib.parse.quote("http://www.sample.com/", safe=""))

Result:

http%3A%2F%2Fwww.sample.com%2F

Or:

from requests.utils import requote_uri
requote_uri("http://www.sample.com/?id=123 abc")

Result:

'https://www.sample.com/?id=123%20abc'
Greg Sadetsky
  • 4,863
  • 1
  • 38
  • 48
Rich Rajah
  • 2,256
  • 1
  • 12
  • 14
16

You’re looking for urllib.parse.urlencode

import urllib.parse

params = {'username': 'administrator', 'password': 'xyz'}
encoded = urllib.parse.urlencode(params)
# Returns: 'username=administrator&password=xyz'
rumpel
  • 7,870
  • 2
  • 38
  • 39
  • This does not work for say `username` and `password` in `http://username:password@www.site.com/` – Gert van den Berg Aug 05 '20 at 14:39
  • Your example uses path params, not query params. For those you need: ` from urllib.parse import quote resource_path = "http://{username}:{password}@www.site.com/" path_params = dict(username='hit there', password='hi there') for k, v in path_params.items(): # specified safe chars, encode everything resource_path = resource_path.replace( '{%s}' % k, quote(str(v)) ) ` – spacether Apr 28 '22 at 16:40