今天看了下tornado的异步初探,把涉及到的装饰器和生成器理了理,又清晰了一些
# coding:utf-8
import time
import _thread
import threading
def gen_coroutine(f):
#打印出参数f,实际上可以看出f就是req_a,
# 第1个被打印
print("f_name:%r"%f.__name__)
#执行wrapper
def wrapper(*args, **kwargs):
#注意下面的f()因为是生成器,所以不会执行代码,只有调用next或者send时才会执行代码,之前把f()函数处理了。。。
gen_f = f() # gen_f为生成器req_a
#执行生成器gen_f,实际就是req_a
r = next(gen_f) # r为生成器long_io
def fun(g):
# ret就是返回结果就是'io result'
ret = next(g) # 执行生成器long_io,
try:
gen_f.send(ret) # 将结果返回给req_a并使其继续执行
except StopIteration:
pass
th1=threading.Thread(target=fun,args=(r,))
#执行新线程,参数r就是生成器long_io
th1.start()
# _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():
#第2被打印
print("开始处理请求req_a")
ret = yield long_io()
print(("ret: %s" % ret))
print("完成处理请求req_a")
def req_b():
#因为req_a在停在了ret = yield long_io()这里,long_io还没被执行所以下面:
#第3被打印
print("开始处理请求req_b")
#这里睡眠的时候long_io被执行
time.sleep(2)
# 第4被打印
print("完成处理请求req_b")
def main():
#因为req_a被装饰器gen_coroutine修饰了,所以这一步相当于req_a=gen_coroutine(req_a),
#先去执行gen_coroutine(req_a),然后得到返回的新函数wrapper,此时,req_a=wrapper,执行req_a实际上就是执行wrapper。
req_a()
time.sleep(0.000001)
req_b()
while 1:
pass
if __name__ == '__main__':
main()
实际打印数据依据time.sleep时间有所不同
理解了装饰器的执行过程,剩下的就简单了,随手写个计算函数执行时间的代码练习下:
#计算函数执行时间
import time,random
def count_time(fun):
def wrapper():
s_time=time.perf_counter()
fun()
e_time=time.perf_counter()
consume=e_time-s_time
print('函数耗时:%r'%consume)
return wrapper
@count_time
def io_fun():
time.sleep(3)
for i in range(10000):
with open('test.txt','a') as fp:
fp.write(str(i)+'\n')
@count_time
def rand():
total_time=0
while True:
total_time+=1
sum=0
# num_list=[]
for i in range(10):
a=random.randint(0,10)
sum+=a
if sum==10:
# print(num_list, len((num_list)))
print('total_time:%r'%total_time)
break
# num_list.append(a)
# if sum(num_list)==10:
# print(num_list,len((num_list)))
# print('total_time:%r'%total_time)
# break
if __name__ == '__main__':
io_fun()
rand()