day37 异步回调和协程
异步回调
"""
    异步任务使用场景
    爬虫
    1.从目标站点下载网页数据 本质就是HTML格式字符串
    2.用re从字符串中提取出你需要的数据
"""
import requests,re,os
from concurrent.futures import  ThreadPoolExecutor,ProcessPoolExecutor
# response = requests.get("https://www.baidu.com")
# htm = response.content.decode("utf-8")
# print(re.findall("href=.*?com",htm))
def get_data(url):
    print("%s 正在请求%s" % (os.getpid(),url))
    response = requests.get(url)
    print("%s 请求%s成功" % (os.getpid(),url))
    return response
def parser(res):
    htm = res.content.decode("utf-8")
    ls = re.findall("href=.*?com", htm)
    print("解析完成! 共%s个连接" % len(ls))
if __name__ == '__main__':
    urls = ["https://www.baidu.com",
            "https://www.sina.com",
            "https://www.tmall.com",
            "https://www.taobao.com",
            "https://www.jd.com",
            "https://www.python.org",
            "https://www.apple.com"]
    pool = ProcessPoolExecutor(3)
    objs = []
    for i in urls:
        obj = pool.submit(get_data,i)
        # res = obj.result() # 会把任务变成串行
        # parser(res)
        objs.append(obj)
    pool.shutdown() # 请求依然是并发,但是请求的结果不能被立即处理
    for i in objs: # 解析数据时串行的
        parser(i.result())
    pool.shutdown() # 请求依然是并发,但是请求的结果不能被立即处理
# 使用异步回调来处理结果
"""
    异步任务使用场景
    爬虫
    1.从目标站点下载网页数据 本质就是HTML格式字符串
    2.用re从字符串中提取出你需要的数据
"""
import requests, re, os
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
# response = requests.get("https://www.baidu.com")
# htm = response.content.decode("utf-8")
# print(re.findall("href=.*?com",htm))
# def get_data(url):
#     print("%s 正在请求%s" % (os.getpid(), url))
#     response = requests.get(url)
#     print("%s 请求%s成功" % (os.getpid(), url))
#     return response
#
#
# def parser(obj):
#
#     res = obj.result()
#     htm = res.content.decode("utf-8")
#     ls = re.findall("href=.*?com", htm)
#     print("%s解析完成! 共%s个连接" % (os.getpid(),len(ls)))
#
# if __name__ == '__main__':
#     urls = ["https://www.baidu.com",
#             "https://www.sina.com",
#             "https://www.tmall.com",
#             "https://www.taobao.com",
#             "https://www.jd.com",
#             "https://www.python.org",
#             "https://www.apple.com"]
#     pool = ProcessPoolExecutor(3)
#
#     for i in urls:
#         obj = pool.submit(get_data, i)
#         # res = obj.result() # 会把任务变成串行
#         # parser(res)
#         obj.add_done_callback(parser)
"""
    什么是回调(函数)
    a 交给 b一个任务  b在执行完成后回过头调用了a的一个函数 就称之为回调
    为什么需要回调函数?
    需要获取异步任务的结果,但是又不应该阻塞(降低效率)
        高效的获取任务结果
    通常异步任务都会和回调函数一起使用
    使用方式:
    使用add_done_callback函数()给Future对象绑定一个回调函数
    注意:在多进程中回调函数 是交给主进程来执行 而在多线程中 回调函数是谁有空谁执行(不是主线程)
"""
# 线程池中使用异步回调
def get_data(url):
    print("%s 正在请求%s" % (current_thread().name, url))
    response = requests.get(url)
    print("%s 请求%s成功" % (current_thread().name, url))
    return response
def parser(obj):
    res = obj.result()
    htm = res.content.decode("utf-8")
    ls = re.findall("href=.*?com", htm)
    print("%s解析完成! 共%s个连接" % (current_thread().name,len(ls)))
if __name__ == '__main__':
    urls = ["https://www.baidu.com",
            "https://www.tmall.com",
            "https://www.taobao.com",
            "https://www.jd.com",
            "https://www.python.org",
            "https://www.apple.com"]
    pool = ThreadPoolExecutor(3)
    for i in urls:
        obj = pool.submit(get_data, i)
        # res = obj.result() # 会把任务变成串行
        # parser(res)
        obj.add_done_callback(parser)
线程队列
"""
    线程队列
    与进程队列的区别 进程队列可以被多进程共享 而线程中的队列 就是一个普通的容器不能进程共享
"""
from queue import Queue,LifoQueue,PriorityQueue
# 1. 先进先出队列
# q = Queue(1)
# q.put("a")
# q.put("b",timeout=1)
#
# print(q.get())
# print(q.get(timeout=2))
# 2.last in first out 后进先出队列(堆栈)
# lq = LifoQueue()
# lq.put("a")
# lq.put("b")
# lq.put("c")
#
#
# print(lq.get())
# print(lq.get())
# print(lq.get())
# 3.优先级队列  取出顺序是 由小到大  优先级可以使数字或字符 只要能够比较大小即可
pq = PriorityQueue()
# pq.put((2,"b"))
# pq.put((3,"c"))
# pq.put((1,"a"))
#
# print(pq.get())
# print(pq.get())
# print(pq.get())
pq.put((["a"],"bdslkfjdsfjd"))
pq.put((["b"],"csdlkjfksdjkfds"))
pq.put((["c"],"asd;kjfksdjfkdsf"))
print(pq.get())
print(pq.get())
print(pq.get())
# print([1] < ["1"])
事件
#     事件
#     是用于协调多个线程工作的,当一个线程要执行某个操作,需要获取另一个线程的状态
#     你要给别人打电话 必须明确知道对方手机买好了
#     作为客户端 要连接服务器 必须明确服务器已经启动了,那么作为启动服务器的一方 如何告知客户端?
#     就通过事件
# """
import time
from threading import Thread
from threading import Event
# 使用变量类完成多线程协作
# is_boot = False
# def start():
#     global is_boot
#     print("正在启动服务器......")
#     time.sleep(5)
#     print("服务器启动成功!")
#     is_boot = True
#
# def connect():
#     while True:
#         if is_boot:
#             print("连接服务器成功!")
#             break
#         else:
#             print("连接服务器失败!")
#         time.sleep(0.5)
#
#
# Thread(target=start).start()
# Thread(target=connect).start()
import time
from threading import Thread
from threading import Event
# 创建一个事件
e = Event() #默认False
def start():
print("正在启动服务器......")
time.sleep(5)
print("服务器启动成功!")
e.set() # 就是把事件的值设置为True
def connect():
# 重试3次
for i in range(3):
    print("等待服务器启动....")
    e.wait(1) # 会阻塞 直到对方把事件设置为True
    if e.isSet():
        print("连接成功!")
        break
    else:
        print("连接失败")
else: #如果3次都没成功 就打印这个消息
    print("服务器没有启动")
Thread(target=start).start()
Thread(target=connect).start()
单线程下实现并发效果
"""
    通过生成器就能完成并发执行
    生成器的特点 只要函数中出现了yield该函数就变成了生成器
    在执行时与普通函数有什么区别??
"""
def test1():
    print(1)
    print(2)
    print(3)
print(test1())
# 使用生成器 实现单线程并发
import time
def task1():
    a = 1
    while True:
        print("task1 run")
        a += 1
        print(a)
        yield
def task2():
    g = task1()
    while True:
        print("task2 run")
        time.sleep(10)
        next(g)
task2()
"""
    单线程并发 是为了提高效率
    对于计算密集型任务 单线程并发 反而降低效率
    对于IO密集型  如果可以在执行IO操作的时候 切换到其他计算任务 就能提高CPU占用率 从而提高效率  
"""
import time
# def task1():
#     a = 0
#     for i in range(10000000):
#         a += i
#         yield
#
# def task2():
#     b = 0
#     g = task1()
#     for i in range(10000000):
#         b += i
#         next(g)
# s = time.time()
# task2()
# print(time.time()-s)
def task1():
    a = 0
    for i in range(10000000):
        a += i
def task2():
    b = 0
    for i in range(10000000):
        b += i
s = time.time()
task1()
task2()
print(time.time()-s)
协程
"""
    协程
    可以这么理解是协助线程更高效的工作
    本质就是单线程实现并发
    也称之为微线程(它比线程更轻量级  单线程下任务的切换 比操作系统切换线程要简单的多)
    为什么有 是因为 在CPython中 无法并行执行任务导致效率低 所以我们就需要一种方案 能够将单线程的效率最大化 就是协程
    Python中 使用Gevent模块来 实现协程  其能在多个任务间进行切换 而且能够自己检测IO
"""
from gevent import monkey
monkey.patch_all()
import gevent
import time
def task1():
    print("task1 run")
    time.sleep(10)
    print("task1 run")
def task2():
    print("task2 run")
    print("task2 run")
g1 = gevent.spawn(task1)
g2 = gevent.spawn(task2)
g1.join()
g2.join()												
											day37 异步回调和协程的更多相关文章
- (并发编程)进程池线程池--提交任务2种方式+(异步回调)、协程--yield关键字 greenlet ,gevent模块
		
一:进程池与线程池(同步,异步+回调函数)先造个池子,然后放任务为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务池子内什么时候装进程:并发的任务 ...
 - Python异步IO之协程(一):从yield from到async的使用
		
引言:协程(coroutine)是Python中一直较为难理解的知识,但其在多任务协作中体现的效率又极为的突出.众所周知,Python中执行多任务还可以通过多进程或一个进程中的多线程来执行,但两者之中 ...
 - 进程&线程(三):外部子进程subprocess、异步IO、协程、分布式进程
		
1.外部子进程subprocess python之subprocess模块详解--小白博客 - 夜风2019 - 博客园 python subprocess模块 - lincappu - 博客园 之前 ...
 - day41 - 异步IO、协程
		
目录 (见右侧目录栏导航) - 1. 前言- 2. IO的五种模型- 3. 协程 - 3.1 协程的概念- 4. Gevent 模块 - 4.1 gevent 基本使用 - 4.2 ...
 - Python的异步编程[0] -> 协程[1] -> 使用协程建立自己的异步非阻塞模型
		
使用协程建立自己的异步非阻塞模型 接下来例子中,将使用纯粹的Python编码搭建一个异步模型,相当于自己构建的一个asyncio模块,这也许能对asyncio模块底层实现的理解有更大的帮助.主要参考为 ...
 - day35:线程队列&进程池和线程池&回调函数&协程
		
目录 1.线程队列 2.进程池和线程池 3.回调函数 4.协程:线程的具体实现 5.利用协程爬取数据 线程队列 1.线程队列的基本方法 put 存 get 取 put_nowait 存,超出了队列长度 ...
 - 异步IO(协程,消息循环队列)
		
同步是CPU自己主动查看IO操作是否完成,异步是IO操作完成后发出信号通知CPU(CPU是被通知的) 阻塞与非阻塞的区别在于发起IO操作之后,CPU是等待IO操作完成再进行下一步操作,还是不等待去做其 ...
 - Python的异步编程[0] -> 协程[0] -> 协程和 async / await
		
协程 / Coroutine 目录 生产者消费者模型 从生成器到异步协程– async/await 协程是在一个线程执行过程中可以在一个子程序的预定或者随机位置中断,然后转而执行别的子程序,在适当的时 ...
 - Python异步IO之协程(二):使用asyncio的不同方法实现协程
		
引言:在上一章中我们介绍了从yield from的来源到async的使用,并在最后以asyncio.wait()方法实现协程,下面我们通过不同控制结构来实现协程,让我们一起来看看他们的不同作用吧- 在 ...
 
随机推荐
- Python基础:一、编程语言分类
			
编程语言主要从以下几个角度进行分类: 编译型和解释型 静态语言和动态语言 强类型语言和弱类型语言 编译型语言和解释型语言 编译和解释的区别是什么? 编译器是把源程序的每一条语句都编译成机器语言,并保存 ...
 - confluence中org.apache.tomcat.util.net.NioEndpoint$Acceptor.run Socket accept failed的解决方法
			
https://www.cnblogs.com/heyongboke/p/9806396.html 1.confluence中报错信息如下: 严重 [http-nio-18090-Acceptor-0 ...
 - yuan先生博客链接
			
Yuan先生的博客网址 1 Web应用 https://www.cnblogs.com/yuanchenqi/articles/8869302.html 2 http协议 https://www ...
 - Docker概念(二)
			
说明: 一直想学Docker,容器.镜像.仓库什么的好难理解就没怎么看了,最近下定决心好好看看,google.Baidu发现这篇好文章,看完差不多有个大概的理解.里面的内容基本上来以下 ...
 - MNIST数据可视化
			
一.数据准备 二.数据说明 可以看出图片数据在偏移量为第16字节开始存,每28X28字节存放一张手写字图片.而label是从偏移量为第8字节开始存,每个字节存放一个label. 三.matlab201 ...
 - 【java】this用法
			
this代表当前类的引用对象:哪个对象调用方法,该方法内部的this就代表那个对象this关键字主要有两三个应用: (1)this调用本类中的属性,也就是类中的成员变量: class People { ...
 - node压缩文件夹
			
前几天遇到一个需求,将一个10G的文件夹打包压缩,并去除黑名单上的文件. node自带的只能压缩文件.网上看了集中方案要么对大文件操作不行,要么只能直接操作文件夹,无法对文件夹遍历筛选. 后来确定使用 ...
 - go语言学习--处理map的无序输出
			
最近工作中遇到了这样的一个场景,需要处理一个无限极分类的问题,对于数据结构的定义首先想到了,map,map[int]map[int]struct.通过两层map的定义归类parent_id和id的关系 ...
 - 数据访问安全--数据库遮罩及断词 Data Masking & Tokenization
			
现在大数据时代几乎无隐私,各政府部门各公司都要求实名制(动不动手机认证,身份证号码认证),但又无力确保数据安全,称为乱象. 其实在2011年,我们就接触过数据库遮罩断词产品,一个澳大利亚公司产品. 简 ...
 - Vue 重点 必须要记住的
			
基础知识: vue的生命周期: beforeCreate/created. beforeMount/mounted. beforeUpdate/updated. beforeDestory/desto ...