Comments (7)
Tornado IOLoop
Reference
from dylanninin.com.
Tornado IOLoop Implementation
Reference
- https://github.com/tornadoweb/tornado/blob/master/tornado/ioloop.py
- https://github.com/tornadoweb/tornado/blob/master/tornado/platform/select.py
- https://github.com/tornadoweb/tornado/blob/master/tornado/platform/epoll.py
- https://github.com/tornadoweb/tornado/blob/master/tornado/platform/kqueue.py
from dylanninin.com.
Tornado HTTPServer
Reference
from dylanninin.com.
Tornado Web Application
Reference
from dylanninin.com.
Tornado and WSGI
Reference
- https://github.com/tornadoweb/tornado/blob/master/tornado/wsgi.py
- http://www.tornadoweb.org/en/stable/wsgi.html
- http://wsgi.readthedocs.io/en/latest/
- http://www.slideshare.net/DylannininGogh/a-byte-of-software-deployment
from dylanninin.com.
Tornado WebSocket
Reference
- https://github.com/tornadoweb/tornado/blob/master/tornado/websocket.py
- https://hpbn.co/websocket/
- https://en.wikipedia.org/wiki/WebSocket
from dylanninin.com.
Tornado Coroutines and Concurrency
1. Future: https://github.com/tornadoweb/tornado/blob/master/tornado/concurrent.py#L132
A Placeholder for an asynchronous result.
A
Future
encapsulates the result of an asynchronous
operation. In synchronous applicationsFutures
are used
to wait for the result from a thread or process pool; in
Tornado they are normally used with.IOLoop.add_future
or by
yielding them in a.gen.coroutine
.
tornado.concurrent.Future
is similar to
concurrent.futures.Future
, but not thread-safe (and therefore
faster for use with single-threaded event loops).
2. web.asynchronous
: https://github.com/tornadoweb/tornado/blob/master/tornado/web.py#L1575
Wrap request handler methods with this if they are asynchronous.
This decorator is for callback-style asynchronous methods; for
coroutines, use the@gen.coroutine
decorator without
@asynchronous
. (It is legal for legacy reasons to use the two
decorators together provided@asynchronous
is first, but
@asynchronous
will be ignored in this case)This decorator should only be applied to the :ref:
HTTP verb methods <verbs>
; its behavior is undefined for any other method.
This decorator does not make a method asynchronous; it tells
the framework that the method is asynchronous. For this decorator
to be useful the method must (at least sometimes) do something
asynchronous.If this decorator is given, the response is not finished when the
method returns. It is up to the request handler to call
self.finish() <RequestHandler.finish>
to finish the HTTP
request. Without this decorator, the request is automatically
finished when theget()
orpost()
method returns
def asynchronous(method):
from tornado.ioloop import IOLoop
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
self._auto_finish = False
with stack_context.ExceptionStackContext(
self._stack_context_handle_exception):
result = method(self, *args, **kwargs)
if result is not None:
result = gen.convert_yielded(result)
# If @asynchronous is used with @gen.coroutine, (but
# not @gen.engine), we can automatically finish the
# request when the future resolves. Additionally,
# the Future will swallow any exceptions so we need
# to throw them back out to the stack context to finish
# the request.
def future_complete(f):
f.result()
if not self._finished:
self.finish()
IOLoop.current().add_future(result, future_complete)
# Once we have done this, hide the Future from our
# caller (i.e. RequestHandler._when_complete), which
# would otherwise set up its own callback and
# exception handler (resulting in exceptions being
# logged twice).
return None
return result
return wrapper
3. gen.coroutine
: https://github.com/tornadoweb/tornado/blob/master/tornado/gen.py#L210
Decorator for asynchronous generators.
Any generator that yields objects from this module must be wrapped
in either this decorator orengine
.Coroutines may "return" by raising the special exception
Return(value) <Return>
. In Python 3.3+, it is also possible for
the function to simply use thereturn value
statement (prior to
Python 3.3 generators were not allowed to also return values).
In all versions of Python a coroutine that simply wishes to exit
early may use thereturn
statement without a value.Functions with this decorator return a
.Future
. Additionally,
they may be called with acallback
keyword argument, which
will be invoked with the future's result when it resolves. If the
coroutine fails, the callback will not be run and an exception
will be raised into the surrounding.StackContext
. The
callback
argument is not visible inside the decorated
function; it is handled by the decorator itself.From the caller's perspective,
@gen.coroutine
is similar to
the combination of@return_future
and@gen.engine
.
def coroutine(func, replace_callback=True):
return _make_coroutine_wrapper(func, replace_callback=True)
4. gen.engine
: https://github.com/tornadoweb/tornado/blob/master/tornado/gen.py#L175
Callback-oriented decorator for asynchronous generators.
This is an older interface; for new code that does not need to be
compatible with versions of Tornado older than 3.0 the
coroutine
decorator is recommended instead.This decorator is similar to
coroutine
, except it does not
return a.Future
and thecallback
argument is not treated
specially.In most cases, functions decorated with
engine
should take
acallback
argument and invoke it with their result when
they are finished. One notable exception is the
~tornado.web.RequestHandler
:ref:HTTP verb methods <verbs>
,
which useself.finish()
in place of a callback argument.
def engine(func):
func = _make_coroutine_wrapper(func, replace_callback=False)
@functools.wraps(func)
def wrapper(*args, **kwargs):
future = func(*args, **kwargs)
def final_callback(future):
if future.result() is not None:
raise ReturnValueIgnoredError(
"@gen.engine functions cannot return values: %r" %
(future.result(),))
# The engine interface doesn't give us any way to return
# errors but to raise them into the stack context.
# Save the stack context here to use when the Future has resolved.
future.add_done_callback(stack_context.wrap(final_callback))
return wrapper
5. gen._make_coroutine_wrapper
: https://github.com/tornadoweb/tornado/blob/master/tornado/gen.py#L248
The inner workings of
@gen.coroutine
and@gen.engine
.
The two decorators differ in their treatment of thecallback
argument, so we cannot simply implement@engine
in terms of
@coroutine
def _make_coroutine_wrapper(func, replace_callback):
# On Python 3.5, set the coroutine flag on our generator, to allow it
# to be used with 'await'.
if hasattr(types, 'coroutine'):
func = types.coroutine(func)
@functools.wraps(func)
def wrapper(*args, **kwargs):
future = TracebackFuture()
if replace_callback and 'callback' in kwargs:
callback = kwargs.pop('callback')
IOLoop.current().add_future(
future, lambda future: callback(future.result()))
try:
result = func(*args, **kwargs)
except (Return, StopIteration) as e:
result = _value_from_stopiteration(e)
except Exception:
future.set_exc_info(sys.exc_info())
return future
else:
if isinstance(result, GeneratorType):
# Inline the first iteration of Runner.run. This lets us
# avoid the cost of creating a Runner when the coroutine
# never actually yields, which in turn allows us to
# use "optional" coroutines in critical path code without
# performance penalty for the synchronous case.
try:
orig_stack_contexts = stack_context._state.contexts
yielded = next(result)
if stack_context._state.contexts is not orig_stack_contexts:
yielded = TracebackFuture()
yielded.set_exception(
stack_context.StackContextInconsistentError(
'stack_context inconsistency (probably caused '
'by yield within a "with StackContext" block)'))
except (StopIteration, Return) as e:
future.set_result(_value_from_stopiteration(e))
except Exception:
future.set_exc_info(sys.exc_info())
else:
Runner(result, future, yielded)
try:
return future
finally:
# Subtle memory optimization: if next() raised an exception,
# the future's exc_info contains a traceback which
# includes this stack frame. This creates a cycle,
# which will be collected at the next full GC but has
# been shown to greatly increase memory usage of
# benchmarks (relative to the refcount-based scheme
# used in the absence of cycles). We can avoid the
# cycle by clearing the local variable after we return it.
future = None
future.set_result(result)
return future
return wrapper
6. gen.Runner
: https://github.com/tornadoweb/tornado/blob/master/tornado/gen.py#L937
Internal implementation of
tornado.gen.engine
.
Maintains information about pending callbacks and their results.
The results of the generator are stored inresult_future
(a
.TracebackFuture
)
# Simplified inner loop of tornado.gen.Runner
def run(self):
# send(x) makes the current yield return x.
# It returns when the next yield is reached
future = self.gen.send(self.next)
def callback(f):
self.next = f.result()
self.run()
future.add_done_callback(callback)
7.async/await support
: http://www.tornadoweb.org/en/stable/guide/coroutines.html#native-coroutines
Python 3.5 introduces the async
and await
keywords (functions using these keywords are also called “native coroutines”). Starting in Tornado 4.3, you can use them in place of yield-based coroutines. Simply use async def foo()
in place of a function definition with the @gen.coroutine
decorator, and await
in place of yield
. The rest of this document still uses the yield
style for compatibility with older versions of Python, but async
and await
will run faster when they are available:
async def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = await http_client.fetch(url)
return response.body
The await
keyword is less versatile than the yield
keyword. For example, in a yield-based coroutine you can yield a list of Futures
, while in a native coroutine you must wrap the list in tornado.gen.multi
. You can also use tornado.gen.convert_yielded
to convert anything that would work with yield
into a form that will work with await
.
While native coroutines are not visibly tied to a particular framework (i.e. they do not use a decorator like tornado.gen.coroutine
or asyncio.coroutine
), not all coroutines are compatible with each other. There is a coroutine runner which is selected by the first coroutine to be called, and then shared by all coroutines which are called directly with await
. The Tornado coroutine runner is designed to be versatile and accept awaitable objects from any framework; other coroutine runners may be more limited (for example, the asyncio coroutine runner does not accept coroutines from other frameworks). For this reason, it is recommended to use the Tornado coroutine runner for any application which combines multiple frameworks. To call a coroutine using the Tornado runner from within a coroutine that is already using the asyncio runner, use the tornado.platform.asyncio.to_asyncio_future
adapter.
Reference
- https://github.com/tornadoweb/tornado/blob/master/tornado/concurrent.py
- https://github.com/tornadoweb/tornado/blob/master/tornado/ioloop.py#L586
- https://github.com/tornadoweb/tornado/blob/master/tornado/web.py#L1575
- https://github.com/tornadoweb/tornado/blob/master/tornado/gen.py#L210
- https://docs.python.org/3/library/types.html#types.coroutine
- http://www.tornadoweb.org/en/stable/guide/coroutines.html#native-coroutines
- http://www.tornadoweb.org/en/stable/coroutine.html
- https://docs.python.org/3/library/asyncio.html
from dylanninin.com.
Related Issues (20)
- 《Linux Shell Scripting Essentials》
- Webhook security
- dhcp
- Security HOT 6
- scrapy
- 《Crypto 101》
- 《Introduction to Machine Learning with Python》
- NoPoint HOT 6
- 《你凭什么做好互联网》
- Email HOT 7
- 《OpenSSL Cookbook》
- 《OpenVPN Cookbook》
- 《聊聊架构》
- Resignation HOT 6
- docsify
- r/Place HOT 1
- Ansible HOT 6
- Architecture
- WeChat API Libraries
- GitHub Issue as a Blog HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dylanninin.com.