Skip to content

Instantly share code, notes, and snippets.

@ploxiln
Created January 20, 2020 02:34
Show Gist options
  • Save ploxiln/c2452decf7c9dd69ad124c66b6ed23b0 to your computer and use it in GitHub Desktop.
Save ploxiln/c2452decf7c9dd69ad124c66b6ed23b0 to your computer and use it in GitHub Desktop.
# run_alt_loop() / run_coro_on_other_thread() by Ben Darnell
# https://github.com/tornadoweb/tornado/issues/2798#issuecomment-575909528
import asyncio
import threading
import concurrent
from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler
# Not asyncio.Future because of multiple threads.
alt_ioloop_fut = concurrent.futures.Future()
def run_alt_loop():
asyncio.set_event_loop(asyncio.SelectorEventLoop())
ioloop = IOLoop()
alt_ioloop_fut.set_result(ioloop)
ioloop.start()
alt_thread = threading.Thread(target=run_alt_loop)
alt_thread.daemon = True
alt_thread.start()
alt_ioloop = alt_ioloop_fut.result()
def run_coro_on_other_thread(f, *args, **kw):
fut = concurrent.futures.Future()
async def wrapper():
try:
res = await f(*args, **kw)
fut.set_result(res)
except Exception as e:
fut.set_exception(e)
alt_ioloop.add_callback(wrapper)
return fut.result()
async def aio_func(msg):
print("started async...")
await asyncio.sleep(2)
print("still going", flush=True)
await asyncio.sleep(2)
print("async done", flush=True)
return "async %s!" % msg
class MainHandler(RequestHandler):
def get(self):
msg = self.get_argument("msg")
resp = run_coro_on_other_thread(aio_func, msg)
self.set_header("Content-Type", "text/plain")
self.write(resp.encode() + b"\n")
if __name__ == "__main__":
app = Application([('/', MainHandler)])
app.listen(8080)
print("listening on port 8080", flush=True)
IOLoop.current().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment