views:

194

answers:

2

I have an application in python with a custom main loop (I don't believe the details are important). I'd like to integrate a simple non-blocking web server into the application which can introspect the application objects and possibly provide an interface to manipulate them. What's the best way to do this?

I'd like to avoid anything that uses threading. The ideal solution would be a server with a "stepping" function that can be called from my main loop, do its thing, then return program control until the next go-round.

The higher-level the solution, the better (though something as monolithic as Django might be overkill).

Ideally, a solution will look like this:

def main():
    """My main loop."""
    http_server = SomeCoolHttpServer(port=8888)

    while True:
        # Do my stuff here...
        # ...

        http_server.next() # Server gets it's turn.

        # Do more of my stuff here...
        # ...
+7  A: 

Twisted is designed to make stuff like that fairly simple

import time

from twisted.web import server, resource
from twisted.internet import reactor

class Simple(resource.Resource):
    isLeaf = True
    def render_GET(self, request):
        return "<html>%s Iterations!</html>"%n

def main():
    global n
    site = server.Site(Simple())
    reactor.listenTCP(8080, site)
    reactor.startRunning(False)
    n=0
    while True:
        n+=1
        if n%1000==0:
            print n
        time.sleep(0.001)
        reactor.iterate()

if __name__=="__main__":
    main()
gnibbler
How did I know Twisted would come up? :) However, your example appears to use its own main loop. How do I get around `reactor.run()`?
David Eyk
Hm. Via <http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorCore.html#iterate>, regarding `reactor.iterate()`: "The reactor must have been started (via the run() method) prior to any invocations of this method. It must also be stopped manually after the last call to this method (via the stop() method). This method is not re-entrant: you must not call it recursively; in particular, you must not call it while the reactor is running." Is this what I'm looking for?
David Eyk
Oh, hey, I just noticed you edited your answer. Thanks for confirming my suspicion, and you may have finally convinced me to give Twisted another chance. :)
David Eyk
A: 

I'd suggest creating a new thread and running a web server (such as Python's built-in SimpleHTTPServer or BaseHTTPServer). Threads really aren't that scary when it comes down to it.

from threading import Event, Thread
import BaseHTTPServer

shut_down = Event()

def http_server():
    server_address = ('', 8000)
    httpd = BaseHTTPServer.HTTPServer(server_address, BaseHTTPServer.BaseHTTPRequestHandler)

    while not shut_down.is_set():
        httpd.handle_request()

thread = Thread(target=http_server)
thread.start()
GothAlice
You have to be careful - if the application objects you are introspecting can change while you are introspecting, a threaded solution is going to be very difficult to get right
gnibbler
Which is why I'd like to avoid threading. Thanks.
David Eyk