Tornado is a "suite" of Open-source servers for Facebook, designed to do the Python Web or use its own extensible functionality to complete an incomplete WSGI protocol that can be used for fast web development, encapsulating epoll performance better. This paper mainly analyzes the asynchronous IO provided by the network part of Tornado, asynchronous event processing and upper Iostream class, and the other modules such as Web Tornado.web are slowly left for analysis.
SOURCE organization:
|---__init__.py
---auth.py
---......
---epoll.c
---ioloop.py
---iostream.py
---...
Tornado Network part of the core of the two modules is ioloop.py and iostream.py, we mainly analyze these two parts.
ioloop.py The main thing is to handle the underlying epoll or other IO multiplexing encapsulation as an asynchronous event.
Iostream.py is primarily a further encapsulation of lower-level asynchronous events, encapsulating a layer of buffer (IO) events.
This column more highlights: http://www.bianceng.cnhttp://www.bianceng.cn/Servers/zs/
This period of time has been learning Tornado asynchronous processing. It mainly uses Ioloop to realize multiplexing.
Here is an example, a friend of Tornado Foundation, a look at the understanding of ~
Import subprocess Import tornado.ioloop import time import fcntl import functools import OS class genericsubprocess (Obje CT): def __init__ (self, Timeout=-1, **popen_args): Self.args = Dict () self.args["stdout"] = Subproc Ess. PIPE self.args["stderr"] = subprocess. PIPE self.args["Close_fds" = True self.args.update (popen_args) Self.ioloop = None Self.ex Piration = None Self.pipe = None Self.timeout = Timeout Self.streams = [] Self.has_timed_o
UT = False def start (self): "" "Spawn the task.
Throws RuntimeError If the task was already started. "" If not Self.pipe is none:raise runtimeerror ("Cannot start task twice") Self.ioloop = tornado.ioloop.i Oloop.instance () if self.timeout > 0:self.expiration = Self.ioloop.add_timeout (Time.time () + Self . Timeout, self.on_timeout) Self.pipe = subprocess. Popen (**self.args) sElf.streams = [(Self.pipe.stdout.fileno (), []), (Self.pipe.stderr.fileno (), [])] fo R FD, d in self.streams:flags = Fcntl.fcntl (FD, FCNTL). F_GETFL) | Os. O_ndelay fcntl.fcntl (FD, FCNTL).
F_SETFL, Flags) Self.ioloop.add_handler (FD, Self.stat,
Self.ioloop.read|self.ioloop.error def on_timeout (self): Self.has_timed_out = True
Self.cancel () def cancel (self): "" "Cancel task execution sends SIGKILL to the child process." " Try:self.pipe.kill () Except:pass def stat (self, *args): ' Check PR
Ocess completion and consume pending I/O data ' ' self.pipe.poll () if not Self.pipe.returncode is None: ' Cleanup handlers and timeouts ' if not self.expiration is None:self.ioloop.remov E_timeout (Self.expiratION) for FD, dest in Self.streams:self.ioloop.remove_handler (FD) ' Schedulle CA Llback (I try to read all pending data) "Self.ioloop.add_callback (self.on_finish) for FD, dest I
n Self.streams:while True:try:data = Os.read (FD, 4096)
If Len (data) = = 0:break Dest.extend ([data]) except: Break @property def stdout (self): return self.get_output (0) @property def stderr (s ELF): Return Self.get_output (1) @property def status (self): return Self.pipe.returncode def ge T_output (self, Index): Return "". Join (Self.streams[index][1]) def on_finish (self): Raise Notimplement Ed () Class Subprocess (genericsubprocess): Def __init__ (self, callback, *args, **kwargs): Self.callback = CA Llback Self.done_callback = False genericsubprocess.__init__ (self, *args, **kwargs) def on_finish (self): if not self.d One_callback:self.done_callback = True ' Prevent calling callback twice ' Self.iolo Op.add_callback (Functools.partial (Self.callback, Self.status, Self.stdout, Self.stderr, self.has_timed_out)) if __ name__ = = "__main__": Ioloop = Tornado.ioloop.IOLoop.instance () def print_timeout (status, stdout, stderr, Has_tim Ed_out): Assert (Status!=0) assert (has_timed_out) print "OK Status:", repr (status), "stdout:", rep R (stdout), "stderr:", repr (stderr), "timeout:", repr (has_timed_out) def print_ok (status, stdout, stderr, Has_timed_ou T): Assert (Status==0) assert (not has_timed_out) print "OK Status:", repr (status), "stdout:", repr (stdout), "stderr:", repr (stderr), "timeout:", repr (has_timed_out) def print_error (status, stdout, stderr, has_timed_
Out): Assert (Status!=0) ASSERT (not has_timed_out) print "OK Status:", repr (status), "stdout:", repr (stdout), "stderr:", repr (Stder R), "timeout:", repr (has_timed_out) def stop_test (): ioloop.stop () t1 = subprocess (print_timeout, timeout =3, args=["Sleep", "5"]) t2 = subprocess (Print_ok, timeout=3, args=["IP", "a"]) T3 = subprocess (Print_ok, TI Meout=3, args=["Sleepdsdasdas", "1"]) T4 = subprocess (Print_error, timeout=3, args=["cat", "/etc/sdfsdfsdfsdfsdfs
Dfsdf "]) T1.start () T2.start () Try:t3.start () assert (false) Except:print" OK " T4.start () Ioloop.add_timeout (Time.time () + stop_test) Ioloop.start ()
This article comes from "Feng Yun, just her." "Blog, please be sure to keep this source http://rfyiamcool.blog.51cto.com/1030776/1236330