0

I have a variable foo = "'totalteams': 10, 'totalrounds': 11"

Why can't I do this?

data=dict(foo)

so I can do

print data['totalteams']

I need to use python 2.5 because of google. How do I do what I want?

thanks

Roman Bodnarchuk
  • 29,461
  • 12
  • 59
  • 75
Jim
  • 11
  • 1

4 Answers4

1
foo = "'totalteams': 10, 'totalrounds': 11"
data = eval("{%s}" % foo)
print data['totalteams']
dminer
  • 1,121
  • 11
  • 9
  • `ast.literal_eval` would be better. – SingleNegationElimination Aug 26 '11 at 18:24
  • 1
    `ast.literal_eval` has been added in Python 2.6: http://docs.python.org/library/ast.html#ast-helpers – rubik Aug 26 '11 at 18:35
  • 1
    One could pass empty dictionary as globals and locals. In this case, `eval()` would not have access to the global and local namespaces and could not call arbitrary functions. It is simple to do, actually: `data = eval("{%s}" % foo, {}, {})`. If someone tries to run malicious code (for example, making `foo = "'a':os.unlink('/etc/resolv.conf')"`) the `os` module would not be found. – brandizzi Aug 26 '11 at 18:48
  • 2
    @brandizzi: Problem with passing in empty dictionaries is that Python injects `__builtins__` into the globals dict. So you'll still have access to the built-in functions, and from there you can import anything you need using `__import__()` You actually need to pass an empty `__builtins__` dict as part of the globals. – kindall Aug 26 '11 at 19:10
  • And injecting an empty `__builtins__` still doesn't prevent you from reaching potentially dangerous facilities (e.g. you can get to all `object` subclasses through the attributes of an empty tuple). The empty `__builtins__` enables a blacklist, but blacklists don't work well as a security measure. – Rosh Oxymoron Aug 26 '11 at 19:39
  • @Rosh how would one get the object subclasses by this way? – brandizzi Aug 27 '11 at 20:22
  • 1
    @brandizzi: Example for locating `subprocess.Popen` and executing a command that way: `[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__ == 'Popen'][0](['ls', '-la']).wait()` – Rosh Oxymoron Aug 27 '11 at 21:59
1

Because a string is not a dictionary. You have a couple of options:

Make a dictionary literal:

data = {'totalteams': 10, 'totalrounds': 11}
print data['totalteams']

Have a JSON string or something similar as your data if you have to work with strings:

# as F.J pointed out, json isn't a built-in in python 2.5 so you'll have to get simplejson or some other json library
import json
foo = '{"totalteams": 10, "totalrounds": 11}'
data = json.loads(foo)
print data['totalteams']

# or
foo = '"totalteams": 10, "totalrounds": 11'
data = json.loads('{%s}' % foo)

Or use eval like dminer's answer, but eval should be a last resort.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • Thank you. is eval more expensive? – Jim Aug 26 '11 at 18:37
  • 1
    `json` is not a built-in for 2.5, so that would only work if he has simplejson or some other JSON module to use. Also, JSON objects requires double quoted strings, so the initial string would need to be converted to `'{"totalteams": 10, "totalrounds": 11}'`. – Andrew Clark Aug 26 '11 at 18:50
  • @F.J I was not aware of either of those things (I don't use JSON very much so) thanks, I'll update my answer. – Seth Carnegie Aug 26 '11 at 19:01
0

you want to use ast.literal_eval. example:

>>> foo = "'totalteams': 10, 'totalrounds': 11"
>>> import ast
>>> ast.literal_eval("{%s}" % foo)
{'totalteams': 10, 'totalrounds': 11}
>>> 

Edit: Hmm.. on ? You might want to consider using a format that is more easily parsed in that environment. PyYAML is standard there, you might consider using that format instead:

>>> import yaml
>>> yaml.load("""
... totalteams: 10
... totalrounds: 11
... """)
{'totalteams': 10, 'totalrounds': 11}
>>> 
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
0

It's probably not as robust, but it's 2.5 compatible:

import re
foo = "'totalteams':10,'totalrounds':11"
m = re.compile("'(\w+)':(\d+)")
t = m.findall(foo)

you will then get a list of tuples which you can decompose and zip into a dictionary

>>> a,b = zip(*t)
>>> a
('totalteams', 'totalrounds')
>>> b
('10', '11')
>>> d = dict(zip(list(a),list(b)))
>>> d
{'totalteams': '10', 'totalrounds': '11'}
>>> 

credit to http://selinap.com/2009/02/unzip-a-python-list/ :: never knew you could unzip a list : )

pyInTheSky
  • 1,459
  • 1
  • 9
  • 24