K
Kirk McDonald
Say I have a database containing chunks of Python code. I already have a
way to easily load, edit, and save them. What is slightly baffling to me
is how I can effectively pass this code some arguments, run it, and
somehow get a return value.
(Acutally, in the process of writing this post, I figured out a pretty
good way of doing it. Here's the rest of my post and the solution I came
up with. Enjoy my thought process!)
Right now I'm thinking of just defining a standard function name, and
using that as the entry/exit point for the DB-stored code. Is this
reasonable? Is there some more Pythonic way?
I'll probably compile the code and store the bytecode to the database
(in addition to the plain text) for faster execution time, as well. It
shouldn't care whether the stored code is a string or a code object.
What if a stored chunk of code doesn't need to return anything? It would
be more convenient to just execute the code without the standard
function. Also, it'd be nice to wrap this in a class:
# module test.py
class Codeobj:
def __init__(self, code=None):
if code: self.code = code
else: self.code = ""
def __call__(self, args=None, **kwargs):
# We can pass in a name/value dictionary
if args: kwargs.update(args)
exec self.code
# We don't need a standard function if we're not returning
# anything
if locals().has_key('std_func_name'):
return std_func_name(**kwargs)
if __name__ == "__main__":
# Load code from the DB
double = """\
def std_func_name(n):
return n*2"""
addthree = """\
def std_func_name(n):
return n+3"""
noreturn = "print 'arg = %s' % kwargs['arg']"
a = Codeobj(double)
b = Codeobj(addthree)
c = Codeobj(noreturn)
# Calling with name/value dictionary
print a(args={'n':5})
# Calling with specific named argument
print b(n=4)
c(arg='foo')
# EOF
$ python test.py
10
7
arg = foo
If I wanted to simplify the 'noreturn' example (well, if there were more
lines of code this might make it simpler), I could have defined it like
this:
noreturn = """\
locals().update(kwargs)
print 'arg = %s' % arg"""
-Kirk McDonald
way to easily load, edit, and save them. What is slightly baffling to me
is how I can effectively pass this code some arguments, run it, and
somehow get a return value.
(Acutally, in the process of writing this post, I figured out a pretty
good way of doing it. Here's the rest of my post and the solution I came
up with. Enjoy my thought process!)
Right now I'm thinking of just defining a standard function name, and
using that as the entry/exit point for the DB-stored code. Is this
reasonable? Is there some more Pythonic way?
I'll probably compile the code and store the bytecode to the database
(in addition to the plain text) for faster execution time, as well. It
shouldn't care whether the stored code is a string or a code object.
What if a stored chunk of code doesn't need to return anything? It would
be more convenient to just execute the code without the standard
function. Also, it'd be nice to wrap this in a class:
# module test.py
class Codeobj:
def __init__(self, code=None):
if code: self.code = code
else: self.code = ""
def __call__(self, args=None, **kwargs):
# We can pass in a name/value dictionary
if args: kwargs.update(args)
exec self.code
# We don't need a standard function if we're not returning
# anything
if locals().has_key('std_func_name'):
return std_func_name(**kwargs)
if __name__ == "__main__":
# Load code from the DB
double = """\
def std_func_name(n):
return n*2"""
addthree = """\
def std_func_name(n):
return n+3"""
noreturn = "print 'arg = %s' % kwargs['arg']"
a = Codeobj(double)
b = Codeobj(addthree)
c = Codeobj(noreturn)
# Calling with name/value dictionary
print a(args={'n':5})
# Calling with specific named argument
print b(n=4)
c(arg='foo')
# EOF
$ python test.py
10
7
arg = foo
If I wanted to simplify the 'noreturn' example (well, if there were more
lines of code this might make it simpler), I could have defined it like
this:
noreturn = """\
locals().update(kwargs)
print 'arg = %s' % arg"""
-Kirk McDonald