class MyTornadoProcess(object):
def __init__(self):
self.io_loop = tornado.ioloop.IOLoop.current()
...
def run(self):
# Not sure what I do here
...
@tornado.gen.coroutine
def wait_for_source_a(self):
# Use coroutine/future or some async library to work around blocking wait
...
# Upon event, call processing_for_source_a()
self.processing_for_source_a(event)
@tornado.gen.coroutine
def wait_for_source_b(self):
# Use coroutine/future or some async library to work around blocking wait
...
# Upon event, call processing_for_source_b()
self.processing_for_source_b(event)
@tornado.gen.coroutine
def processing_for_source_a(self):
# Use some async library for a blocking task
...
@tornado.gen.coroutine
def processing_for_source_b(self):
# Use some async library for a blocking task
...
if __name__ == '__main__':
proc = MyTornadoProcess()
proc.run()--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornad...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
# do stuff
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornado+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornado+unsubscribe@googlegroups.com.
I see, so having io_loop.run_sync(main) together with:@gen.coroutinedef main():while True:# do stuffwill effectively keeps the IOLoop running forever, even though run_sync() itself executes a function once and exits.
A related question: if a function is decorated with @gen.coroutine because inside that function there is 'yield' which makes the function a generator, does it mean that we must also yield this function when we call it? Or, we only need to do so when the generator returns a value? If the generator does not return a value, then we call the function directly without 'yield'. For example:@gen.coroutinedef post_url():response = yield async_http_client.fetch('some url', method='POST', body=json.dumps({...}))if response.error:logger.error(...)because post_url() does not return any value, we just call post_url() directly without using 'yield' in some other function?
IOLoop.current().run_sync(main)
IOLoop.current().start()
from datetime import datetime
import urllib.parse
import simplejson as json
from tornado import gen, ioloop, httpclient
from toredis import Client
httpclient.AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')
http_client = httpclient.AsyncHTTPClient()
rds = Client()
def log(message):
print("{0}: {1}".format(datetime.now().strftime('%H:%M:%S.%f')[:-3], message))
@gen.coroutine
def connect_redis(socket_path='/tmp/redis.sock', pwd='123456'):
yield gen.Task(rds.connect_usocket, socket_path)
status = yield gen.Task(rds.auth, pwd)
if status == 'OK':
log('Redis authenticated')
status = yield gen.Task(rds.select, '0')
if status == 'OK':
log('Redis DB 0 selected')
@gen.coroutine
def fetch_task():
log('Waiting for new task ...')
key, task = yield gen.Task(rds.brpop, 'queue:test', timeout=0)
log('Received a new task: {}'.format(task))
task_dict = json.loads(task)
task_id = task_dict['ID']
log('Processing task #{}'.format(task_id))
res = yield process_task(task_dict)
log('Received response: {}'.format(res))
log('Finished task #{}'.format(task_id))
@gen.coroutine
def process_task(task):
# Up to 3 tries
for _ in range(3):
try:
response = yield http_client.fetch('http://httpbin.org/post', method='POST',
headers={'Content-Type': 'application/x-www-form-urlencoded'},
body=urllib.parse.urlencode({'Text': task['Body']}))
yield gen.sleep(5)
log('Request POSTed')
return response.body
except httpclient.HTTPError as e:
log('Error when POSTing: %s', e.args[0])
continue
@gen.coroutine
def main():
yield connect_redis()
while True:
yield fetch_task()
if __name__ == '__main__':
io_loop = ioloop.IOLoop.current()
io_loop.run_sync(main)15:06:09.408: Waiting for new task ...
15:06:16.077: Received a new task: b'{"ID": 1, "Body": "Hello!"}'
15:06:16.077: Processing task #1
15:06:21.568: Request POSTed
15:06:21.568: Received response: b'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "Text": "Hello!"\n }, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip,deflate", \n "Content-Length": "13", \n "Content-Type": "application/x-www-form-urlencoded", \n "Host": "httpbin.org", \n "User-Agent": "Mozilla/5.0 (compatible; pycurl)"\n }, \n "json": null, \n "origin": "205.154.255.224", \n "url": "http://httpbin.org/post"\n}\n'
15:06:21.569: Finished task #1
15:06:21.569: Waiting for new task ...
15:06:21.569: Received a new task: b'{"ID": 2, "Body": "World!"}'
15:06:21.569: Processing task #2
15:06:26.784: Request POSTed
15:06:26.784: Received response: b'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "Text": "World!"\n }, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip,deflate", \n "Content-Length": "13", \n "Content-Type": "application/x-www-form-urlencoded", \n "Host": "httpbin.org", \n "User-Agent": "Mozilla/5.0 (compatible; pycurl)"\n }, \n "json": null, \n "origin": "205.154.255.224", \n "url": "http://httpbin.org/post"\n}\n'
15:06:26.784: Finished task #2
15:06:26.784: Waiting for new task ...
# do stuff
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornado+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornado+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Thanks Ben. I see the reasoning for using 'yield' vs. not using it, but I don't quite get your first point about keep run_sync(main) running forever.IOLoop.current().run_sync(main)
IOLoop.current().start()It is true that the above will restart the IOLoop immediately once run_sync (and main()) is finished, but the program will be simply stuck in an IOLoop, so how do I run main() again and keep it running forever?