python django异步访问_Python Django 协程报错,进程池、线程池与异步调用、回调机制...

一、问题描述

在Django视图函数中,导入 gevent 模块

importgeventfrom gevent importmonkey; monkey.patch_all()from gevent.pool import Pool

启动Django报错:

MonkeyPatchWarning: Monkey-patching outside the main native thread. Some APIs will notbe available. Expect a KeyError to be printed at shutdown.from gevent importmonkey; monkey.patch_all()

MonkeyPatchWarning: Monkey-patching not on the main thread; threading.main_thread().join() will hang froma greenletfrom gevent import monkey; monkey.patch_all()

原因在于执行这行 monkey.patch_all() 代码时报错了。

既然Django不能使用协程,那我需要使用异步执行,怎么办?

请看下文

二、进程池、线程池与异步调用、回调机制

进程池、线程池使用案例

进程池与线程池使用几乎相同,只是调用模块不同~!!

from concurrent.futures import ProcessPoolExecutor #进程池模块

from concurrent.futures import ThreadPoolExecutor #线程池模块

importos, time, random#下面是以进程池为例, 线程池只是模块改一下即可

deftalk(name):print('name: %s pis%s run' %(name,os.getpid()))

time.sleep(random.randint(1, 3))if __name__ == '__main__':

pool= ProcessPoolExecutor(4) #设置线程池大小,默认等于cpu核数

for i in range(10):

pool.submit(talk,'进程%s' % i) #异步提交(只是提交需要运行的线程不等待)

#作用1:关闭进程池入口不能再提交了 作用2:相当于jion 等待进程池全部运行完毕

pool.shutdown(wait=True)print('主进程')

异步调用与同步调用

concurrent.futures模块提供了高度封装的异步调用接口

ThreadPoolExecutor:线程池,提供异步调用

ProcessPoolExecutor: 进程池,提供异步调用

同步调用

from concurrent.futures import ProcessPoolExecutor #进程池模块

importos, time, random#1、同步调用: 提交完任务后、就原地等待任务执行完毕,拿到结果,再执行下一行代码(导致程序串行执行)

deftalk(name):print('name: %s pis%s run' %(name,os.getpid()))

time.sleep(random.randint(1, 3))if __name__ == '__main__':

pool= ProcessPoolExecutor(4)for i in range(10):

pool.submit(talk,'进程%s' % i).result() #同步迪奥用,result(),相当于join 串行

pool.shutdown(wait=True)print('主进程')

异步调用

from concurrent.futures import ProcessPoolExecutor #进程池模块

importos, time, randomdeftalk(name):print('name: %s pis%s run' %(name,os.getpid()))

time.sleep(random.randint(1, 3))if __name__ == '__main__':

pool= ProcessPoolExecutor(4)for i in range(10):

pool.submit(talk,'进程%s' % i) #异步调用,不需要等待

pool.shutdown(wait=True)print('主进程')

回调机制

可以为进程池或线程池内的每个进程或线程绑定一个函数,该函数在进程或线程的任务执行完毕后自动触发,并接收任务的返回值当作参数,该函数称为回调函数

#parse_page拿到的是一个future对象obj,需要用obj.result()拿到结果

p.submit(这里异步调用).add_done_callback(方法)

案例:下载解析网页页面

importtimeimportrequestsfrom concurrent.futures import ThreadPoolExecutor #线程池模块

defget(url):print('GET %s' %url)

response= requests.get(url) #下载页面

time.sleep(3) #模拟网络延时

return {'url': url, 'content': response.text} #页面地址和页面内容

defparse(res):

res= res.result() #!取到res结果 【回调函数】带参数需要这样

print('%s res is %s' % (res['url'], len(res['content'])))if __name__ == '__main__':

urls={'http://www.baidu.com','http://www.360.com','http://www.iqiyi.com'}

pool= ThreadPoolExecutor(2)for i inurls:

pool.submit(get, i).add_done_callback(parse)#【回调函数】执行完线程后,跟一个函数

本文参考链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值