Tornado asynchronous shallow solution

7.1 Asynchronous know

1. Synchronization

We use two functions to simulate two client requests, and execute processes:

# ! / Usr / bin / env python3 
# - * - Coding: UTF-8 - * - 
#   @time: 2020/3/9 11:15 
#   @author: zhangmingda 
#   @file: asynchronization.py 
#   @Software: PyCharm 
#   the Description: understanding the asynchronous works 
DEF Req_A ():
     '' ' simulation request A ' '' 
    Print ( ' starts processing the request A ' )
     Print ( ' complete processing request A ' ) 

DEF Req_B ():
     '' ' simulation request A '' ' 
    Print ( ' starts processing the request B ')
    print( ' Complete processing request B ' )
 DEF main ():
     "" " analog tornado frame, processing the two requests " "" 
    Req_A () 
    Req_B () 

IF  the __name__ == " __main__ " : 
    main ()

Results of the:

D: \ Python3_study \ tornado1 \ Scripts \ python.exe D: /Python3_study/tornado1/asynchronization.py
start processing the request A
complete processing request A
starts processing request B
is completed a processing request B

Synchronization is performed sequentially step by step, always performed in the same step, the step does not executing the next step.

Think about it, if you need to perform a time-consuming task (such as IO) while processing the request req_a, how its execution?

Import Time 


DEF Req_A ():
     '' ' simulation request A ' '' 
    Print ( ' starts processing the request A ' ) 
    long_io () 
    Print ( ' complete processing request A ' ) 

DEF Req_B ():
     '' ' simulation request A ' ' ' 
    Print ( ' start processing request B ' )
     Print ( ' complete processing request B ' )
 DEF main ():
     "" " analog tornado frame, processing the two requests " ""
    req_a()
    req_b()
def long_io():
    '''IO analog time-consuming operation '' ' 
    Print ( ' start IO operations ' ) 
    the time.sleep ( . 5 )
     Print ( " complete IO operation " )
     return  " IO ComPlate !! " 

IF  the __name__ == " __main__ " : 
    main ()

Implementation process:

D: \ Python3_study \ tornado1 \ Scripts \ python.exe D: /Python3_study/tornado1/asynchronization.py
starts processing the request A
starts operation IO
completion IO operation
completion request processing A
starts processing request B
is completed a processing request B

In the above test, we see a time-consuming operation to execute the code blocking live, that req_a untreated finished req_b unenforceable.

How we solve time-consuming operation blocking code execution?

2. Asynchronous

For the time-consuming process, and we give it to someone else (such as its another thread) to perform, and we continue to deal with down, when people finish time-consuming operation and then the results back to us, this is what we call asynchronous .

We use easy to understand mechanisms to implement asynchronous thread.

2.1 The principle of writing callback

# coding:utf-8

import time
import thread

def long_io(callback): """将耗时的操作交给另一线程来处理""" def fun(cb): # 回调函数作为参数 """耗时操作""" print "开始执行IO操作" time.sleep(5) print "完成IO操作,并执行回调函数" cb("io result") # 执行回调函数 thread.start_new_thread(fun, (callback,)) # 开启线程执行耗时操作 def on_finish(ret): """回调函数""" print "开始执行回调函数on_finish" print "ret: %s" % ret print "完成执行回调函数on_finish" def req_a(): print "开始处理请求req_a" long_io(on_finish) print "离开处理请求req_a" def req_b(): print "开始处理请求req_b" time.sleep(2) # 添加此句来突出显示程序执行的过程 print "完成处理请求req_b" def main(): req_a() req_b() while 1: # 添加此句防止程序退出,保证线程可以执行完 pass if __name__ == '__main__': main() 

Implementation process:

开始处理请求req_a
离开处理请求req_a
开始处理请求req_b
开始执行IO操作
完成处理请求req_b
完成IO操作,并执行回调函数
开始执行回调函数on_finish
ret: io result
完成执行回调函数on_finish

Characterized by the presence of multiple asynchronous program step, i.e. codes that belong to the same process may be performed simultaneously on different pace.

2.2 The principle of writing coroutines

When writing the program using a callback function asynchronous, a need to belong to the present logic (processing request a) is split into two code execution and functions req_a on_finish, which synchronization program written vary greatly. The synchronization program easier to understand the business logic, so we can use the wording synchronization code to write asynchronous program?

Recall that yield the role of keywords?

initial version

# coding:utf-8

import time
import thread

gen = None # 全局生成器,供long_io使用 def long_io(): def fun(): print "开始执行IO操作" global gen time.sleep(5) try: print "完成IO操作,并send结果唤醒挂起程序继续执行" gen.send("io result") # 使用send返回结果并唤醒程序继续执行 except StopIteration: # 捕获生成器完成迭代,防止程序退出 pass thread.start_new_thread(fun, ()) def req_a(): print "开始处理请求req_a" ret = yield long_io() print "ret: %s" % ret print "完成处理请求req_a" def req_b(): print "开始处理请求req_b" time.sleep(2) print "完成处理请求req_b" def main(): global gen gen = req_a() gen.next() # 开启生成器req_a的执行 req_b() while 1: pass if __name__ == '__main__': main() 

Implementation process:

开始处理请求req_a
开始处理请求req_b
开始执行IO操作
完成处理请求req_b
完成IO操作,并send结果唤醒挂起程序继续执行
ret: io result
完成处理请求req_a

updated version

We write in the above version although very similar to the synchronization code written in a way req_a, but in the main the call req_a when it can not simply regarded as an ordinary function, but need to be treated as a generator.

Now, we are trying to attempt to modify, so write req_a are similar to the main synchronization code.

# coding:utf-8

import time
import thread

gen = None # 全局生成器,供long_io使用 def gen_coroutine(f): def wrapper(*args, **kwargs): global gen gen = f() gen.next() return wrapper def long_io(): def fun(): print "开始执行IO操作" global gen time.sleep(5) try: print "完成IO操作,并send结果唤醒挂起程序继续执行" gen.send("io result") # 使用send返回结果并唤醒程序继续执行 except StopIteration: # 捕获生成器完成迭代,防止程序退出 pass thread.start_new_thread(fun, ()) @gen_coroutine def req_a(): print "开始处理请求req_a" ret = yield long_io() print "ret: %s" % ret print "完成处理请求req_a" def req_b(): print "开始处理请求req_b" time.sleep(2) print "完成处理请求req_b" def main(): req_a() req_b() while 1: pass if __name__ == '__main__': main() 

Implementation process:

开始处理请求req_a
开始处理请求req_b
开始执行IO操作
完成处理请求req_b
完成IO操作,并send结果唤醒挂起程序继续执行
ret: io result
完成处理请求req_a

The final version

Just completed version is still not ideal, because there is a global variable for long_io gen to use. We now rewrite the program again, the elimination of global variables gen.

# coding:utf-8

import time
import thread

def gen_coroutine(f): def wrapper(*args, **kwargs): gen_f = f() # gen_f为生成器req_a r = gen_f.next() # r为生成器long_io def fun(g): ret = g.next() # 执行生成器long_io try: gen_f.send(ret) # 将结果返回给req_a并使其继续执行 except StopIteration: pass thread.start_new_thread(fun, (r,)) return wrapper def long_io(): print "开始执行IO操作" time.sleep(5) print "完成IO操作,yield回操作结果" yield "io result" @gen_coroutine def req_a(): print "开始处理请求req_a" ret = yield long_io() print "ret: %s" % ret print "完成处理请求req_a" def req_b(): print "开始处理请求req_b" time.sleep(2) print "完成处理请求req_b" def main(): req_a() req_b() while 1: pass if __name__ == '__main__': main() 

Implementation process:

开始处理请求req_a
开始处理请求req_b
开始执行IO操作
完成处理请求req_b
完成IO操作,yield回操作结果
ret: io result
完成处理请求req_a

The final version is to understand the most simple asynchronous programming model Tornado principle, however, is not the Tornado implementation mechanism asynchronous thread, but epoll, epoll is about asynchronous process to execute and monitor the callbacks.

One thing to note is that the version we have implemented strict sense it can not be regarded as coroutines, because suspend and wake up two programs are implemented on two threads, and Tornado epoll to use asynchronous, and the program hangs always wake up on a thread, scheduled by Tornado himself, belongs to the coroutine in the true sense. Having said that, it does not prevent us understand Tornado asynchronous programming principles.

Think

  1. Tornado in the coroutine is asynchronous, this sentence right?
  2. Tornado appeared yield is asynchronous, this sentence right?
  3. Understanding how the program will yield hangs? Tornado in the program and how to understand the yield pending asynchronous?

Guess you like

Origin www.cnblogs.com/zhangmingda/p/12448109.html