什么是异步及使用场景?
写代码过程中,经常会碰到,某一个函数,可能需要执行很久,才会返回,那么,我们现在让程序在这里死等着让它执行完成,很影响代码性能,因此,需要借用异步处理!比如如下demo
def my_func():
demo()
pass
def demo():
# long time
import time
import random
time.sleep(10 * random.randint(1,5))#IO密集型操作
return 'Success or Faild'
如何使用异步,以及异步的返回结果如何进行回调?
异步的原理就是,这个时候,不再自己执行函数,把任务交出去,给其他人去执行,总之,原理就是我不再等你完事,我要干自己事情去了!
那么怎么交出去呢?
1.可以多开个线程交出去,使用装饰器(单机处理)
def async_demo(func):
from threading import Thread
def wrapper(*args, **kwargs):
thr = Thread(target=func, args=args, kwargs=kwargs)
thr.start()
return wrapper
def my_func():
demo()
print('my_func todo')
pass
@async_demo
def demo():
# long time
import time
import random
time.sleep(10 * random.randint(1,5))#IO密集型操作
return 'Success or Faild'
2.可以交给redis内存,以队列形式,供其他进程或者线程去消耗(分布式处理,或者单机多进程处理)
代码请自行研究,这里暂不做举例,涉及代码较多(queue队列)
3.使用协程(单机单线程)
yield也起到挂起程序的作用
import time
def foo():
print('Running in foo') #1
yield
time.sleep(3)
print('Explicit context switch to foo again') #3
def bar():
print('Explicit context to bar') #4
yield
time.sleep(3)
print('Implicit context switch back to bar') #6
next(foo())
next(bar())
print('haha')
gevent
import gevent
def foo():
print('Running in foo') #1
gevent.sleep(2) #2
print('Explicit context switch to foo again') #3
def bar():
print('Explicit context to bar') #4
gevent.sleep(1) #5
print('Implicit context switch back to bar') #6
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
注意:
虽然异步比较适用于大部分的等待时间较长的操作,但是作为python程序,因为有全局锁(GIL)的存在,即同一时刻只有一个线程在CPU中跑,所以,对于计算密集型操作,是不适合本机多开线程的,反而会影响执行速度!
关于网络、磁盘IO密集型和CPU密集型:
对于网络、磁盘IO来说,因为会有很多等待时间,比如,请求资源到等待返回资源这段时间(也叫IO等待),这个线程是啥事都干不了的,还不如让其他线程继续进行请求或作其他操作,这个时候多线程就有用了;
但是CPU密集型的操作来说:因为要持续跑CPU,这个线程实质上是基本没有休息时间的,因为在持续占用CPU进行操作,所以,这个时候,python多线程用处不大,还会因为频繁切换线程而耗费资源!