How to eval a file

Alexander Schmolck a.schmolck at gmx.net
Sat Feb 22 12:36:35 EST 2003


d95-bli at nada.kth.se (Björn Lindberg) writes:

> I'm writing a program with a "configuration file" if you will, that
> looks something like this:
> 
> --------------------------------
> collection = '''Abba %sdabba'''
> topic = '''Gucko %s'''
> --------------------------------
> 
> I have trouble getting this information into Python. I was hoping I
> could read this file as a string and then eval() it, to get the
> variables collection & topic set to the respective strings in the
> local context. Ie, in a class method:
> 
>     def read_file(name):

You mean ``def read_file(self, name):`` I take it?

>         f = open(name, 'r')
>         string = f.read()
>         eval(string)
>         
>         self.collection = collection
>         self.topic = topic
>         ...
> 
>         f.close()

The code is not only broken, it's also a bad way to set about it, e.g. why
would you want to mess up your functions namespace? Think of what would happen
if the configuration file contained a name you use (e.g. "f", "self" etc.).
Also, if you don't have control over the file's contents, someone might just
enter code that formats your harddisk.

> 
> This gives the following error message:
> 
>     File "<string>", line 3
>     collection = '''<h3%s</h3>'''
>                ^
>     SyntaxError: invalid syntax

This is because eval only works for expressions (i.e. something that returns a
value), assignment ('=') is a statement (as are 'if', 'for' etc.). So 

  f = eval('3 + 4')

will work fine.

  eval('f = 3 + 4')

won't. If you want to execute arbitrary code (and not just expressions), use
exec or execfile.

> 
> So I tried using execfile(name) instead, but that doesn't work
> either. 

It does, you're just not using it correctly (and don't give many hints as to
what exactly you did). Try this [UNTESTED]:
  
  namespace = {}
  execfile(filename, namespace)
  self.collection = namespace['collection']


> 
> The only thing I can come up with now is to import the file. This has
> a number of drawbacks however: (i) I would have to modify the module
> search path, (ii) The file would have to be named .py, (iii) It looks
> ugly (at least to me) to have an import statement inside a function,
> (iv) I am not even sure it would work as I expect.
> 
> Is there another way?

Yes. Doing it properly (without any exec*s). If your configuration file just
looks like

 var1 = '''some string'''
 var2 = '''some other string'''

then parse it, it isn't particularly difficult.


alex




More information about the Python-list mailing list