views:

101

answers:

5

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))
+4  A: 

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.

David Wolever
Thanks for the upvotes, but I think Jeethu's answer — ConfigObject + unrepr — is probably a better answer.
David Wolever
This one works fine for me.
giodamelio
+2  A: 

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)
jimbob
+2  A: 

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.

Jeethu
+3  A: 

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

Ashish
It's true that `eval` will work… But IMO it's the wrong tool for this job; the same end can be achieved with a trivial regular expression without any of the risk.
David Wolever
@David, agree that use of eval is unsafe (that's why I commented that use eval() with caution in my original solution) I have changed code to use a safer version of eval() which would only evaluate if value is tuple in this case, else it will raise exception.
Ashish
Interestingly, 'set literals', which were supposedly [backported] from Python 3.1 into 2.7, aren't supported by 2.7's `ast.literal_eval()` function (which I suspect is a bug). On the other hand `eval('{1,2,3}')` **does** work.
martineau
+3  A: 

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.

l33tnerd
Ah, interesting — I didn't know about the `literal_eval` function. It would be less evil then straight up `eval` (and maybe even preferable to a regex parser or somesuch?)
David Wolever
Well, it saves you from having to write a regex, provides more functionality than one (just in case), and is built-in.
l33tnerd