How do I do this? (eval() on the left hand side)

Craig Ringer craig at postnewspapers.com.au
Tue Dec 7 22:30:46 CET 2004


On Wed, 2004-12-08 at 05:12, It's me wrote:

> There are many situations where this is useful.   For instance, you might be
> getting an input which is a string representing the name of a variable and
> you wish to evaluate the expression (like a calculator application, for
> instance).

While I do agree it can be handy, I also think that most possible uses
are also _very_ _dangerous_ security-wise. If possible it'd be safer to
write your code a different way to avoid the evaluation of user-supplied
expressions. For example, you could use a dictionary to store the
'user-accessible' namespace and have all their operations act on that.

You could probably do something _like_ what you want with exec() and
repr, but it'll break as soon as it encounters input that repr can't
make an exec()able string from. It's also really ugly.

If you know what namespace you want to modify ahead of time, or can pass
it to the function doing the modifying, you can also use
getattr()/setattr() or dict methods to do it. For example:

>>> # modify the globals space on the __main__ module
>>> import __main__
>>> varname = 'fred'
>>> setattr(__main__, varname, 'blech')
>>> fred
'blech'
>>> # same thing
>>> __main__.__dict__[varname] = 'yech!'
>>> fred
'yech!'
>>> # modify the attributes of some random object
>>> class dummy(object):
...	pass
...
>>> obj = dummy()
>>> setattr(obj, varname, 'eew')
>>> obj.fred
'eew'
>>> # same thing using the object's __dict__, NOT RECOMMENDED
>>> # outside the class's own methods.
>>> obj.__dict__[varname] = 'unwise'
>>> obj.fred
'unwise'

This, however, won't do you much good if you don't know what you'll be
modifying. I know the locals() and globals() functions exist, but have
always been leery of the idea of modifying their contents, and am not
sure what circumstances you could do so under even if you felt like
doing so.

In general, it'll be _much_ safer to use a generic object with
getattr/setattr or a dict than to try to work with your local or global
namespaces like this...

--
Craig Ringer




More information about the Python-list mailing list