views:

131

answers:

4

Hi,

I need to store python code in a database and load it in some kind of bootstrap.py application for execution. I cannot use filesystem because I'm using GAE, so this is my only choice.

However I'm not a python experienced user.

I already was able to load 1 line of code and run it using eval, however a piece of code with two lines or more gave me a "invalid syntax" error.

I'm also thinking if it's possible to extend the "import" loader to implement the DB loading.

Thanks!

+2  A: 

I somewhat agree with the commentators above, it sounds kind of dangerous. However:

I experimented a little with App Engine Console ( http://con.appspot.com/console/ ), and eval() indeed tended to throw SyntaxError's.

Instead, the exec statement might be your friend ( http://docs.python.org/release/2.5.2/ref/exec.html ).

I managed to run this in App Engine Console:

>>> exec "def f(x):\n    x = x + 1\n    y = 10\n    return x + y"
>>> f(10)
21

So try the exec statement, but remember the many, many (many!) perils of code coming directly from end-users.

Jacob Oscarson
Thank you. I already solved my problem. I think I got misunderstood on the problem. My intent is to enable the application to be self updated when needed instead of asking the user to download GAE SDK to updated the application after installed. I'll post my implementation here.
HGF
However, why do you think this may be dangerous?
HGF
This would be dangerous if the code above came from end-users, it exposes your app to attacks and/or stupidity. Even if the user group is very controlled, you never know.
Jacob Oscarson
Ok. This is a controlled environment. Code in DB will only be replaced by the app itself, and will probably be downloaded from a single thrusted source.
HGF
+1  A: 

I was able to do what I intent after reading more about Python dynamic code loading.

Here is the sample code. I removed headers to be lighter:

Thanks anyway!

=============

class DynCode(db.Model):
    name = db.StringProperty()
    code = db.TextProperty(default=None)

=============

class MainHandler(webapp.RequestHandler):
    def get(self):
        dyn = DynCode()
        dyn = "index"
        dyn.code = """
from google.appengine.ext import webapp
class MainHandler(webapp.RequestHandler):
    def get(self):
        self.response.out.write("Hello World\\n")
        self.response.out.write("Hello World 2\\n")
"""
        dyn.put()
        self.response.out.write("OK.")

def main():
    application = webapp.WSGIApplication([('/update', MainHandler)], debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

==================================

def main():
    query = DynCode.all()
    dyncodes = query.fetch(1)
    module = imp.new_module('mymodule')
    for dyn in dyncodes:
        exec dyn.code in module.__dict__

    application = webapp.WSGIApplication([('/', module.MainHandler)], debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

=======================

HGF
So how does the `DynCode` get loaded? How does `dyn.code` get tested? What state is the application in if there is a syntax error in `dyn.code`?
msw
DynCode is a simple file imported in the last one. The testing I will do in a separate place. There is no difference of loading a syntax broken code from a separate file or loading it from a string.
HGF
A: 

I was able to do what I intent after reading more about Python dynamic code loading.

Oops, too bad that it is broken by design because you don't understand the operating environment:

App Engine uses multiple web servers to run your application, and automatically adjusts the number of servers it is using to handle requests reliably. A given request may be routed to any server, and it may not be the same server that handled a previous request from the same user.

msw
That's not the case, if the code he's loading only has to service the current request.
Nick Johnson
msw. I do understand the environment. Thanks for your concern.
HGF
+1  A: 

If you want a more robust mechanism, you probably want to read PEP302, which describes input hooks. You can use these to import code rather than having to eval it.

Nick Johnson
Thanks! This is very welcome.
HGF