Ordering of urlencoded tuples incorrect

B

benlucas99

I'm having problems with the ordering of the tuples produced by
urllib.urlencode. Taking an example straight from the docs and so
doing the following:

import urllib
...
params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
print params

The documentation for urlencode( query[, doseq]) says: "The order of
parameters in the encoded string will match the order of parameter
tuples in the sequence" but I'm getting:

"eggs=2&bacon=0&spam=1"

Should this not produce: "spam=1&eggs=2&bacon=0" ?

I am seeing this "incorrect" result using Python 2.5.1 and
ActivePython 2.3.2 (both on XP SP2). What am I doing wrong? I've
been googling around for an answer but I'm a Python newbie and so
don't know the ropes yet.

Thanks for any help.

Ben
 
M

MRAB

I'm having problems with the ordering of the tuples produced by
urllib.urlencode. Taking an example straight from the docs and so
doing the following:

import urllib
...
params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
print params

The documentation for urlencode( query[, doseq]) says: "The order of
parameters in the encoded string will match the order of parameter
tuples in the sequence" but I'm getting:

"eggs=2&bacon=0&spam=1"

Should this not produce: "spam=1&eggs=2&bacon=0" ?

I am seeing this "incorrect" result using Python 2.5.1 and
ActivePython 2.3.2 (both on XP SP2). What am I doing wrong? I've
been googling around for an answer but I'm a Python newbie and so
don't know the ropes yet.
You're passing a dict, which is unordered. It will accept a tuple or
list of 2-tuples or a dict:
>>> # tuple of 2-tuples
>>> urllib.urlencode((('spam', 1), ('eggs', 2), ('bacon', 0))) 'spam=1&eggs=2&bacon=0'
>>>
>>> # list of 2-tuples
>>> urllib.urlencode([('spam', 1), ('eggs', 2), ('bacon', 0)]) 'spam=1&eggs=2&bacon=0'
>>>
>>> # dict
>>> urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
'eggs=2&bacon=0&spam=1'

but I doubt the order will matter in practice.
 
J

John Machin

I'm having problems with the ordering of the tuples produced by
urllib.urlencode.  Taking an example straight from the docs and so
doing the following:

What are "the docs" you are reading that include such an example? The
docs distributed with Python 2.5.1 from www.python.org have only this:
"""
urlencode( query[, doseq])

Convert a mapping object or a sequence of two-element tuples to a
``url-encoded'' string, suitable to pass to urlopen() above as the
optional data argument. This is useful to pass a dictionary of form
fields to a POST request. The resulting string is a series of
key=value pairs separated by "&" characters, where both key and value
are quoted using quote_plus() above. If the optional parameter doseq
is present and evaluates to true, individual key=value pairs are
generated for each element of the sequence. When a sequence of two-
element tuples is used as the query argument, the first element of
each tuple is a key and the second is a value. The order of parameters
in the encoded string will match the order of parameter tuples in the
sequence. The cgi module provides the functions parse_qs() and
parse_qsl() which are used to parse query strings into Python data
structures.
"""
        import urllib
        ...
        params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
        print params

The documentation for urlencode( query[, doseq]) says: "The order of
parameters in the encoded string will match the order of parameter
tuples in the sequence" but I'm getting:

"query" can be either a mapping object (e.g. a dictionary, as you have
used) or a sequence of 2-tuples. No such guarantee as you quote above
can be made for a mapping; mappings are just not orderable.
If you want order, give it a sequence, like this:

| >>> import urllib
| >>> urllib.urlencode((('spam', 1), ('eggs', 2), ('bacon', 0)))
| 'spam=1&eggs=2&bacon=0'

HTH,
John
 
B

benlucas99

I'm having problems with the ordering of the tuples produced by
urllib.urlencode. Taking an example straight from the docs and so
doing the following:

What are "the docs" you are reading that include such an example? The
docs distributed with Python 2.5.1 fromwww.python.orghave only this:
"""
urlencode( query[, doseq])

Convert a mapping object or a sequence of two-element tuples to a
``url-encoded'' string, suitable to pass to urlopen() above as the
optional data argument. This is useful to pass a dictionary of form
fields to a POST request. The resulting string is a series of
key=value pairs separated by "&" characters, where both key and value
are quoted using quote_plus() above. If the optional parameter doseq
is present and evaluates to true, individual key=value pairs are
generated for each element of the sequence. When a sequence of two-
element tuples is used as the query argument, the first element of
each tuple is a key and the second is a value. The order of parameters
in the encoded string will match the order of parameter tuples in the
sequence. The cgi module provides the functions parse_qs() and
parse_qsl() which are used to parse query strings into Python data
structures.
"""


import urllib
...
params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
print params
The documentation for urlencode( query[, doseq]) says: "The order of
parameters in the encoded string will match the order of parameter
tuples in the sequence" but I'm getting:

"query" can be either a mapping object (e.g. a dictionary, as you have
used) or a sequence of 2-tuples. No such guarantee as you quote above
can be made for a mapping; mappings are just not orderable.
If you want order, give it a sequence, like this:

| >>> import urllib
| >>> urllib.urlencode((('spam', 1), ('eggs', 2), ('bacon', 0)))
| 'spam=1&eggs=2&bacon=0'

HTH,
John

Thanks guys, the explanations really helped. I knew I was missing
something fundamental.

The docs I'm referring is section "18.7.3 Examples" in the Python
Library Reference, 18th April, 2007, Release 2.5.1 But looking at it
now I guess the server side procsssing that post request may not care
about ordering (unlike the web API I'm trying to call).

cheers,
Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top