Problem
From a Quixote handler, you want to start some lengthy computational task, but don't want to make the user's browser wait while the task is performed.
Solution
Note: this solution is written for Quixote 1.x. The basic idea should still work for Quixote 2, depending on the server technology used.
XXX write this
# This doesn't work if you use cgi. import datetime, threading, time _q_exports = ['job'] def _q_index[html](request): header(request, 'long') '<a href="job">Start job</a>' footer(request) def header[html](request, header, meta=''): '''<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> %s <title>%s</title> </head> <body> ''' % (meta, header) def footer[html](request): '\n </body>\n</html>' class Thread: def __init__(self): self.thread = None self.status = [] def add_status(self, s): self.status.append((datetime.datetime.now(), s)) thread = None semaphore = threading.Semaphore() def do_job(): thread.add_status('Beginning job.') thread.add_status('Feeling tired, sleeping 20 seconds.') time.sleep(20) thread.add_status('Waking up.') thread.add_status('Tired again, sleeping 20.') time.sleep(20) thread.add_status('Waking up.') thread.add_status("Now I'm done.") def start_job(): global thread semaphore.acquire() try: if not thread: # Start the thread thread = Thread() thread.thread = threading.Thread(target=do_job) thread.thread.start() finally: semaphore.release() def get_status(): status = [] running = False semaphore.acquire() try: if thread: status = thread.status[:] if thread.thread and thread.thread.isAlive(): running = True finally: semaphore.release() return running, status def job[html](request): start_job() running, status = get_status() if running: #request.response.set_header('Refresh', '5; URL=.') header(request, 'Job', '<meta http-equiv="Refresh" content="5; URL=%s">' % \ request.get_url()) '<h1>Job status</h3>\n' else: header(request, 'Job') '<h3>Last job log</h3>\n' for date, msg in status: '%s %s<br />\n' % (date.isoformat(), msg) footer(request)