进行运行的三种状态:运行、就绪、阻塞
阻塞、非阻塞、同步、异步
同步调用与异步调用:
异步调用:
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os
def task(i):
print(f'{os.getpid()}开始任务')
time.sleep(random.randint(1,3))
print(f'{os.getpid()}任务结束')
return i
if __name__=='__main__':
#异步调用
pool=ProcessPoolExecutor()
for i in range(10):
pool.submit(task,i)
pool.shutdown(wait=True)
#shutdown:让我的主进程等待进程池中所有的子进程都结束任务之后,再执行,有点类似与join
#shutdown:在上一个进程池没有完成所有的任务之前,不允许添加新的任务
#一个任务时通过一个函数实现的,任务完成得返回值就是函数得返回值
print('====主')
同步调用:
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os
def task(i):
print(f'{os.getpid()}开始任务')
time.sleep(random.randint(1,3))
print(f'{os.getpid()}任务结束')
return i
if __name__ == '__main__':
pool=ProcessPoolExecutor()
for i in range(10):
obj=pool.submit(task,i)
#obj是一个动态对象,返回当前的而对象状态,有可能运行中,有可能(就绪,堵塞)还有可能是结束了
obj.result()#必须等到这个任务完成后,返回了结果之后,在执行下一个任务
print(f'任务结果{obj.result()}')
pool.shutdown(wait=True)
#shutdown:让我的主进程等待进程池中所有的子进程都结束任务之后,在执行,有点类似join
#shutdown:在上一个进程池没有完成所有的任务之前,不允许添加新的任务
#一个任务是通过一个函数实现的,任务完成了,他的返回就是函数的返回值
print('====主')
异步如何取结果?
第一种方式:统一回收结果
方式一:异步调用,统一回收结果
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
import os
import random
def task(i):
print(f'{os.getpid()}任务开始')
time.sleep(random.randint(1,3))
print(f'{os.getpid()}任务结束')
return i
if __name__ == '__main__':
l1=[]
pool=ProcessPoolExecutor()
for i in range(10):
obj=pool.submit(task,i)
l1.append(obj)
pool.shutdown(wait=True)
print(l1)
for i in l1:
print(i.result())
print('全')
#统一回收结果:我不能马上收到任何一个已经完成任务的返回值,我只能等到所有任务结束统一回收
第二种方式:一个个回收
import requests
def task(url):
"""模拟的就是爬取多个源代码,一定有IO操作"""
ret=requests.get(url)
if ret.status_code==200:
return ret.text
def parse(content):
"""模拟对数据进行分析 一般没有IO 如果都有IO用回调函数就没有意义"""
return len(content)
if __name__ == '__main__':
"""串行,耗费时间长"""
ret=task('http://www.baidu.com')
print(parse(ret))
ret = task('http://www.JD.com')
print(parse(ret))
异步调用+回调函数
浏览器工作原理:向服务器发送一个请求,服务端验证你的请求,如果正确,给你的浏览器返回一个文件,浏览器接收到文件,将文件里面的代码渲染成你看到的漂亮美丽的模样
什么叫爬虫?
pip模块为第三方模块,安装里面requests模块
模拟浏览器
import requests#导入requests模块
ret=request.get('http://www.baidu.com')#
if ret.status_code==200:#如果请求状态是成功
print(ret.text)#则把源码打印出来
异步调用+回调函数(版本一)
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os
import requests
def task(url):
"""模拟的就是爬去多个源代码 一定有IO操作"""
ret=requests.get(url)
if ret.status_code==200:
return ret.text
def parse(content):
"""模拟对数据进行分析 一般没有IO 如果有IO 会回调函数就没有意义"""
return len(content)
if __name__ == '__main__':
"""开启线程池,并发并行的执行"""
url_list = [
'http://www.baidu.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.taobao.com',
'https://www.cnblogs.com/jin-xin/articles/7459977.html',
'https://www.luffycity.com/',
'https://www.cnblogs.com/jin-xin/articles/9811379.html',
'https://www.cnblogs.com/jin-xin/articles/11245654.html',
'https://www.sina.com.cn/',
]
pool=ThreadPoolExecutor(4)
obj_list=[]
for url in url_list:
obj=pool.submit(task,url)
obj_list.append(obj)
pool.shutdown(wait=True)
for res in obj_list:
print(parse(res.result()))
print("===主")
#版本一:
#1.异步发出10个任务,并发的执行,但是统一的接受所有的任务返回值(效率低,不能实时的获取结果)
#2.分析结果流程是串行,影响效率
#for res in obj_list:
# print(parse(res.result()))
异步调用+回调函数(版本二)
#版本二:针对版本一的缺点2,让串行变成并发或者并行
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os
import requests
def task(url):
"""模拟的就是爬取多个源代码 一定有IO操作"""
ret=requests.get(url)
if ret.status_code==200:
return parse(ret.text)
def parse(content):
return len(content)
if __name__ == '__main__':
url_list = [
'http://www.baidu.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.taobao.com',
'https://www.cnblogs.com/jin-xin/articles/7459977.html',
'https://www.luffycity.com/',
'https://www.cnblogs.com/jin-xin/articles/9811379.html',
'https://www.cnblogs.com/jin-xin/articles/11245654.html',
'https://www.sina.com.cn/',
]
pool=ProcessPoolExecutor(4)
obj_list=[]
for url in url_list:
obj=pool.submit(task,url)
obj_list.append(obj)
'''
# 1 在开一个线程进程池,并发并行的处理. 再开一个线程进程池,开销大.
# 2 将原来的任务扩大,
版本一:
线程池设置4个线程, 异步发起10个任务,每个任务是通过网页获取源码, 并发执行,
最后统一用列表回收10个任务, 串行着分析源码.
版本二:
线程池设置4个线程, 异步发起10个任务,每个任务是通过网页获取源码+数据分析, 并发执行,
最后将所有的结果展示出来.
耦合性增强了.
并发执行任务,此任务最好是IO阻塞,才能发挥最大的效果
'''
pool.shutdown(wait=True)
for res in obj_list:
print(res.result())
异步调用+回调函数(版本三)
#版本三:
#基于异步调用回收所有任务结果我要做实时回收结果
#并发执行任务每个任务只是处理IO阻塞,不能增加新功能
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os
import requests
def task(url):
"""模拟就是爬去多个源代码 一定有IO操作"""
ret=requests.get(url)
if ret.status_code==200:
return ret.text
def parse(obj):
print(len(obj.result()))
if __name__ == '__main__':
# 开启线程池,并发并行的执行
url_list = [
'http://www.baidu.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.JD.com',
'http://www.taobao.com',
'https://www.cnblogs.com/jin-xin/articles/7459977.html',
'https://www.luffycity.com/',
'https://www.cnblogs.com/jin-xin/articles/9811379.html',
'https://www.cnblogs.com/jin-xin/articles/11245654.html',
'https://www.sina.com.cn/',
]
pool=ThreadPoolExecutor(4)
for url in url_list:
obj=pool.submit(task,url)
obj.add_done_callback(parse)
"""
线程池设置4个线程,异步发起10个任务,每个任务都是通过网页获取源码,并发执行
当一个任务完成之后,将parse这个分析代码的任务交由剩余的空闲的线程去执行,你这个线程继续处理其他任务
如果进程池+回调:回调函数由主进程去执行
如果线程池+回调:回调函数由空闲线程去执行
"""
异步和回调的区别?
原文:https://www.cnblogs.com/zhangdadayou/p/11432097.html