0

I am using standard library string template. From the template, I make a list that contains all the identifiers. For example:

list_of_identifiers = ['id', 'username', 'url']

I want to iterate this list to substitute the template identifier.

xml = string.Template(xml_template)
for i in range(len(list_of_identifiers)):
    xml.substitute(list_of_identifiers[i] = somevalue)

But I am getting a syntax error SyntaxError: keyword can't be an expression. I want to use the string literal in the list_of_identifiers[i] as a keyword. Is it possible?


Edit

What I am basically doing here is reading a csv file with the values of identifiers and then substituting the values into the xml template. But the csv file can include other fields than just the identifiers. In other words the csv file could read:

id, username, orientation, eye, expression, url
1, admin, left, sunglasses, sad, http://google.com

However the identifiers that I want to substitute are [id, username, url] only. So I generate two lists:

list_of_identifiers = ['id', 'username', 'url']
col_index = ['0','1','5']

As you might tell, col_index is the the indexes of the identifiers in the csv row. So I iterate both of the lists:

with open(dataFile, 'rb') as csvFile_obj:
    reader = csv.reader(csvFile_obj)
    for row in reader:
        #
        #some code to filter out first line of csv file
        #
        xml = string.Template(xml_template)
        for i in range(len(list_of_identifiers)):
            xml.substitute(list_of_identifiers[i]= row[col_index[i]])
Community
  • 1
  • 1
Megool
  • 963
  • 2
  • 8
  • 29

2 Answers2

1

As mentioned elsewhere, substitute doesn't do what you think it does - you need to substitute all the variables at once. Using DictReader makes things slightly easier for you too:

columns = ['id', 'username', 'url']

with open(dataFile, 'rb') as csvFile_obj:
    reader = csv.DictReader(csvFile_obj)
    for row in reader:
        xml = string.Template(xml_template).substitute({
            col: row[ident]
            for col in columns
        })
Eric
  • 95,302
  • 53
  • 242
  • 374
0

What you're trying to do isn't directly possible. Keywords in function calls have to be identifiers, not expressions. More importantly, however, keywords are static things--the identifier itself is the keyword, not the current value of some variable with that name.

If you want to dynamically pass keywords to a function call, you can use dict unpacking. For example, the following are equivalent:

spam(name=value)
spam(**{'name': value})

So, in your case:

xml.substitute{**{list_of_identifiers[i]: somevalue})

However, you're probably overcomplicating the code. Notice that substitute can just take a mapping as a (non-keyword) argument, so there's no need to unpack one into separate keyword arguments. Plus, instead of looping and substituting each one separately, why not just substitute them all at once?


A couple of side notes:

  • If you want to loop over all elements of a list, just do for identifier in list_of_identifiers:.
  • substitute doesn't do what you think it does. It returns a string with the template variables substituted for their arguments; it doesn't modify the template in-place, partially substituting.
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • I edited the post to give more details. Can I still do the way you suggested? `xml.substitute{**{list_of_identifiers[i]: row[col_index[i]]})` – Megool May 24 '15 at 17:36
  • @YunCHan Of course you can. (Why not try it, instead of asking?) But that just shows that you're overcomplicating things even more. For example, why not use a `DictReader` instead of trying to reproduce what it does? – abarnert May 24 '15 at 17:51
  • I was wondering if I might have to use a bit differently given the detailed situation because I tried it and had errors saying `File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/string.py", line 176, in substitute return self.pattern.sub(convert, self.template)` `File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/string.py", line 166, in convert val = mapping[named]`. Trying to debug now! – Megool May 24 '15 at 18:05