exec
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Mar 1 09:21:31 EST 2012
On Thu, 01 Mar 2012 14:07:15 +0100, Rolf Wester wrote:
> Hi,
>
> I would like to define methods using exec like this:
>
> class A:
> def __init__(self):
> cmd = "def sqr(self, x):\n return x**2\nself.sqr = sqr\n"
> exec cmd
> a = A()
> print a.sqr(a, 2)
That's... nasty, nasty code. I would hate to have to maintain that. I
hope you have a VERY good reason for doing it instead of the more obvious:
class B:
def __init__(self):
def sqr(self, x):
return x**2
self.sqr = sqr
or the even more obvious:
class C:
def sqr(self, x):
return x**2
And I *really* hope that you aren't getting the string to be exec'ed from
untrusted users. The world has enough code injection vulnerabilities.
If you don't understand what a code injection vulnerability is, or why
using exec on untrusted strings is dangerous, stop what you are doing and
don't write another line of code until you have read up it. You can start
here:
http://en.wikipedia.org/wiki/Code_injection
https://www.owasp.org/index.php/Injection_Flaws
and remember, code injection attacks are now the most frequent attack
vector of viruses, worms and malware, ahead of buffer overflow attacks.
Class C is, of course, the only one where a.sqr is an actual method, that
is, a.sqr(5) works instead of a.sqr(a, 5). You can fix this by doing one
of the following:
(1) Your function sqr() doesn't actually use self, so why require it? Get
rid of it!
class A:
def __init__(self):
# still nasty...
cmd = "def sqr(x):\n return x**2"
exec cmd
self.sqr = sqr # or put this in the cmd string (yuck)
class B:
def __init__(self):
# better, but still weird
def sqr(x):
return x**2
self.sqr = sqr
(2) Perhaps you actually do need access to self. So turn the function
into a proper method.
from types import MethodType
class A:
def __init__(self):
# still nasty...
cmd = "def sqr(self, x):\n return x**2\n"
exec cmd
self.sqr = MethodType(sqr, self)
class B:
def __init__(self):
def sqr(self, x):
return x**2
self.sqr = MethodType(sqr, self)
(3) My guess is that there is probably some sort of closure-based
solution that will work, or delegation, or composition. But given the toy
example you have shown, I don't know what that might be. If you explain
what you are actually doing, perhaps someone can suggest a better
solution.
--
Steven
More information about the Python-list
mailing list