After using cgi.parse_qs(), how to convert the result (dictionary) back to query string? Looking for something similar to urllib.urlencode().
Python 3
urllib.parse.urlencode(query, doseq=False, [...])
Convert a mapping object or a sequence of two-element tuples, which may contain str or bytes objects, to a percent-encoded ASCII text string.
— Python 3 urllib.parse docs
A dict is a mapping.
Legacy Python
urllib.urlencode(query[, doseq])
Convert a mapping object or a sequence of two-element tuples to a “percent-encoded” string... a series of key=value pairs separated by '&' characters...
— Python 2.7 urllib docs
In python3, slightly different:
from urllib.parse import urlencode
urlencode({'pram1': 'foo', 'param2': 'bar'})
output: 'pram1=foo¶m2=bar'
for python2 and python3 compatibility, try this:
try:
#python2
from urllib import urlencode
except ImportError:
#python3
from urllib.parse import urlencode
You're looking for something exactly like urllib.urlencode()!
However, when you call parse_qs() (distinct from parse_qsl()), the dictionary keys are the unique query variable names and the values are lists of values for each name.
In order to pass this information into urllib.urlencode(), you must "flatten" these lists. Here is how you can do it with a list comprehenshion of tuples:
query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)
Maybe you're looking for something like this:
def dictToQuery(d):
query = ''
for key in d.keys():
query += str(key) + '=' + str(d[key]) + "&"
return query
It takes a dictionary and convert it to a query string, just like urlencode. It'll append a final "&" to the query string, but return query[:-1] fixes that, if it's an issue.
Related
here defining a variable:
sms_param = '{\"website\":\"hello\"}'
and it print out ok like this : {"website":"hello"}, but i want to pass a dynamic value to its value, so its format should like this: {\"website\":\"{0}\"}.format(msg), but it output a KeyError, I have no idea of this Error, and change all kinds of string format such as triple quotation and change {0} with %s, but all seems useless. how can i solve it.
My suggestion is using json.loads()
>>> sms_param = '{\"website\":\"hello\"}'
>>> import json
>>> json.loads(sms_param)
{'website': 'hello'}
What you can do is using json.loads() convert the json string to dictionary and then change the value, finally convert it back to string
A common technique for rendering values from template strings looks like this:
>>> num = 7
>>> template = 'there were {num} dwarves'
>>> print template.format(**locals())
there were 7 dwarves
This approach works for any data type that has a __str__ method, e.g. dicts:
>>> data = dict(name='Bob', age=43)
>>> template = 'goofy example 1 {data}'
>>> print template.format(**locals())
goofy example 1 {'age': 43, 'name': 'Bob'}
However it doesn't work when a dict item is referenced by key:
>>> template = 'goofy example 2 {data["name"]}'
>>> print template.format(**locals())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: '"name"'
It's inconvenient, and seems odd, that an identifier that's valid in code outside the format string is invalid when used within the format string. Am I missing something? Is there a way to do this?
I'd like to be able to reference an element several layers down in a nested dictionary structure, like somedict['level1key']['level2key']['level3key']. So far my only workable approach has been to copy these values to a scalar variable just for string formatting, which is icky.
You can do it by using {data[name]} instead of {data["name"]} in the string.
The types of things you can specify in a format string are restricted. Arbitrary expressions aren't allowed, and keys are interpreted in a simplified way, as described in the documentation:
it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string.
In this case, you can get your key out because it's a simple alphanumeric string, but, as the docs suggest, you can't always necessarily do it. If you have weird dict keys, you may have to change them to use them in a format string, or resort to other methods (like concatening string values explicitly with +).
I have unicode u"{'code1':1,'code2':1}" and I want it in dictionary format.
I want it in {'code1':1,'code2':1} format.
I tried unicodedata.normalize('NFKD', my_data).encode('ascii','ignore') but it returns string not dictionary.
Can anyone help me?
You can use built-in ast package:
import ast
d = ast.literal_eval("{'code1':1,'code2':1}")
Help on function literal_eval in module ast:
literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.
You can use literal_eval. You may also want to be sure you are creating a dict and not something else. Instead of assert, use your own error handling.
from ast import literal_eval
from collections import MutableMapping
my_dict = literal_eval(my_str_dict)
assert isinstance(my_dict, MutableMapping)
EDIT: Turns out my assumption was incorrect; because the keys are not wrapped in double-quote marks ("), the string isn't JSON. See here for some ways around this.
I'm guessing that what you have might be JSON, a.k.a. JavaScript Object Notation.
You can use Python's built-in json module to do this:
import json
result = json.loads(u"{'code1':1,'code2':1}") # will NOT work; see above
I was getting unicode error when I was reading a json from a file. So this one worked for me.
import ast
job1 = {}
with open('hostdata2.json') as f:
job1= json.loads(f.read())
f.close()
#print type before converting this from unicode to dic would be <type 'unicode'>
print type(job1)
job1 = ast.literal_eval(job1)
print "printing type after ast"
print type(job1)
# this should result <type 'dict'>
for each in job1:
print each
print "printing keys"
print job1.keys()
print "printing values"
print job1.values()
You can use the builtin eval function to convert the string to a python object
>>> string_dict = u"{'code1':1, 'code2':1}"
>>> eval(string_dict)
{'code1': 1, 'code2': 1}
I have a XML file with some elements like this:
<RMS>[14.470156174, 14.470156174, 14.485567944, 14.496014765]</RMS>
I want to get a list with all the elements
So i tried some Regex with the following code:
string = dom.getElementsByTagName('RMS')[0].toxml()
string2 = re.findall("[\-]*[0-9]*\.[0-9]*", string)
Now, when I want to print the list, it looks like this:
[u'14.470156174', u'14.470156174', u'14.485567944', u'14.496014765']
What's going on with the 'u'?
Are there any ideas how to solve the problem?
Thanks for helping.
Strings that start with a u are unicode string literals. Since XML contains unicode data, the XML parser returns your data in the correct type, which is the python unicode() type.
You do not need to remove them, you do not have a problem. You may want to read up on Unicode and Python in the Python Unicode HOWTO but there is no problem here.
Since these are numbers, you can convert the unicode values straight to float instances.
There is no need to use regex here. In fact, your regex may not work for some floats such as 1.4e1.
Since you are using minidom you could do this:
import xml.dom.minidom as minidom
import ast
content = "<RMS>[14.470156174, 14.470156174, 14.485567944, 14.496014765]</RMS> "
dom = minidom.parseString(content)
text = dom.getElementsByTagName('RMS')[0].childNodes[0].wholeText
If you
print(text)
you get
[14.470156174, 14.470156174, 14.485567944, 14.496014765]
but if you
print(repr(text))
you get
u'[14.470156174, 14.470156174, 14.485567944, 14.496014765]'
The u indicates that text is a unicode object, not a str object. Similarly, your code produces a list of unicode objects. When you print a list, Python prints the repr of each of the elements inside the list. This is why you see
[u'14.470156174', u'14.470156174', u'14.485567944', u'14.496014765']
Now upon rereading your question, I see you want a list of the elements in text. Since they are numbers, I assume you want a list of floats. In that case, you could use ast.literal_eval:
values = ast.literal_eval(text)
print(values)
yields
[14.470156174, 14.470156174, 14.485567944, 14.496014765]
where values is a list of floats.
I have a config file like this.
[rects]
rect1=(2,2,10,10)
rect2=(12,8,2,10)
I need to loop through the values and convert them to tuples.
I then need to make a tuple of the tuples like
((2,2,10,10), (12,8,2,10))
Instead of using a regex or int/string functions, you could also use the ast module's literal_eval function, which only evaluates strings that are valid Python literals. This function is safe (according to the docs).
http://docs.python.org/library/ast.html#ast.literal_eval
import ast
ast.literal_eval("(1,2,3,4)") # (1,2,3,4)
And, like others have said, ConfigParser works for parsing the INI file.
To turn the strings into tuples of ints (which is, I assume, what you want), you can use a regex like this:
x = "(1,2,3)"
t = tuple(int(v) for v in re.findall("[0-9]+", x))
And you can use, say, configparser to parse the config file.
Considering that cp is the ConfigParser object for the cfg file having the config.
[rects]
rect1=(2,2,10,10)
rect2=(12,8,2,10)
>> import ast
>> tuple(ast.literal_eval(v[1]) for v in cp.items('rects'))
((2,2,10,10), (12,8,2,10))
Edit : Changed eval() to a safer version literal_eval()
From python docs - literal_eval() does following :
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None
You can simply make a tuple of tuples like
new_tuple = (rect1,rect2) # ((2,2,10,10), (12,8,2,10))
If you want to loop through values
for i in rect1+rect2:
print i
If you want to regroup the numbers you could do
tuple_regrouped = zip(rect1,rect2) #((2,12),(2,8),(10,2), (10,10))
EDIT:
Didn't notice the string part. If you have lines in strings, like from reading a config file, you can do something like
# line = "rect1 = (1,2,3,4)"
config_dict = {}
var_name, tuple_as_str = line.replace(" ","").split("=")
config_dict[var_name] = tuple([int(i) for i in tuple_as_str[1:-1].split(',')])
# and now you'd have config_dict['rect1'] = (1,2,3,4)
The easiest way to do this would be to use Michael Foord's ConfigObject library. It has an unrepr mode, which'll directly convert the string into a tuple for you.