gj13 asyncio并发编程

13.1 事件循环

asyncio

包含各种特定系统实现的模块化事件循环

传输和协议抽象

对TCP、UDP、SSL、子进程、延时调用以及其他的具体支持

模仿futures模块但适用于事件循环使用的Future类

基于 yield from 的协议和任务,可以让你用顺序的方式编写并发代码

必须使用一个将产生阻塞IO的调用时,有接口可以把这个事件转移到线程池

模仿threading模块中的同步原语、可以用在单线程内的协程之间

import asyncio
import time  # 不再这使用同步阻塞的time

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    # time.sleep(2) 不要这样写
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.imooc.com") for i in range(10)]
    loop.run_until_complete(asyncio.wait(tasks))
    print(time.time() - start_time)

"""
start get url
start get url
start get url
start get url
start get url
start get url
start get url
start get url
start get url
start get url
end get url
end get url
end get url
end get url
end get url
end get url
end get url
end get url
end get url
end get url
2.001918077468872
"""

# 使用asyncio

import asyncio
import time

from functools import partial  # 偏函数

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    return "lewen"

def callback(url, future):
    print(url)
    print("send callback email to lewen")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()  # 事件循环

    # task = asyncio.ensure_future(get_html("http://www.imooc.com")) # 任务的两种不同写法
    task = loop.create_task(get_html("http://www.imooc.com"))

    task.add_done_callback(partial(callback, "http://www.imooc.com"))
    loop.run_until_complete(task)
    print(task.result())

"""
start get url
http://www.imooc.com
send callback email to lewen
lewen
"""

# 获取协程的返回值

import asyncio
import time

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.imooc.com") for i in range(10)]
    # loop.run_until_complete(asyncio.gather(*tasks))
    loop.run_until_complete(asyncio.wait(tasks))
    # print(time.time()-start_time)

    # gather和wait的区别
    # gather更加高层 high-level    分组
    group1 = [get_html("http://projectsedu.com") for i in range(2)]
    group2 = [get_html("http://www.imooc.com") for i in range(2)]
    group1 = asyncio.gather(*group1)
    group2 = asyncio.gather(*group2)
    # group2.cancel()   #取消
    loop.run_until_complete(asyncio.gather(group1, group2))
    print(time.time() - start_time)

# wait 和 gather

13.2 协程嵌套

13.3 call_soon、call_later、call_at、call_soon_threadsafe

import asyncio

def callback(sleep_times, loop):
    print("success time {}".format(loop.time()))

def stoploop(loop):
    loop.stop()

# call_later, call_at
if __name__ == "__main__":
    loop = asyncio.get_event_loop()

    # 马上执行队列里面的task
    # loop.call_soon(callback, 4, loop)
    # loop.call_soon(stoploop, loop)

    # call_later() 等待多少秒后执行
    # loop.call_later(2, callback, 2, loop)
    # loop.call_later(1, callback, 1, loop)
    # loop.call_later(3, callback, 3, loop)

    # call_at()  在某一时刻执行
    now = loop.time()
    loop.call_at(now+2, callback, 2, loop)
    loop.call_at(now+1, callback, 1, loop)
    loop.call_at(now+3, callback, 3, loop)

    loop.run_forever()

    # loop.call_soon_threadsafe()

view

13.4 ThreadPoolExecutor+asyncio

# 使用多线程:在协程中集成阻塞io
# 数据库等阻塞式IO
import asyncio
from concurrent.futures import ThreadPoolExecutor
import socket
from urllib.parse import urlparse

def get_url(url):
    # 通过socket请求html
    url = urlparse(url)
    host = url.netloc
    path = url.path
    if path == "":
        path = "/"

    # 建立socket连接
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # client.setblocking(False)
    client.connect((host, 80))  # 阻塞不会消耗cpu

    # 不停的询问连接是否建立好, 需要while循环不停的去检查状态
    # 做计算任务或者再次发起其他的连接请求

    client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode("utf8"))

    data = b""
    while True:
        d = client.recv(1024)
        if d:
            data += d
        else:
            break

    data = data.decode("utf8")
    html_data = data.split("\r\n\r\n")[1]
    print(html_data)
    client.close()

if __name__ == "__main__":
    import time

    start_time = time.time()
    loop = asyncio.get_event_loop()
    executor = ThreadPoolExecutor(3)  # 线程池
    tasks = []
    for url in range(20):
        url = "http://www.baidu.com/s?wd={}/".format(url)
        task = loop.run_in_executor(executor, get_url, url)  # 将阻塞的放到执行器里面
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print("last time:{}".format(time.time() - start_time))

# 将线程池直接应用到协程里面

13.5 asyncio模拟http请求

# coding=utf-8
# asyncio 没有提供http协议的接口 aiohttp
import asyncio
from urllib.parse import urlparse

async def get_url(url):
    # 通过socket请求html
    url = urlparse(url)
    host = url.netloc
    path = url.path
    if path == "":
        path = "/"

    # 建立socket连接
    reader, writer = await asyncio.open_connection(host, 80)
    writer.write("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode("utf8"))
    all_lines = []
    async for raw_line in reader:
        data = raw_line.decode("utf8")
        all_lines.append(data)
    html = "\n".join(all_lines)
    return html

async def main():
    tasks = []
    for url in range(20):
        url = "http://www.baidu.com/s?wd={}/".format(url)
        tasks.append(asyncio.ensure_future(get_url(url)))
    for task in asyncio.as_completed(tasks):
        result = await task
        print(result)

if __name__ == "__main__":
    import time

    start_time = time.time()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    print(‘last time:{}‘.format(time.time() - start_time))

13.6 future和task

future 结果容器

task 是 future 的子类,协程和future之间的桥梁,启动协程

13.7 asyncio同步和通信

13.8 aiohttp实现高并发爬虫

原文地址:https://www.cnblogs.com/wenyule/p/10420240.html

时间: 2024-10-13 00:29:48

gj13 asyncio并发编程的相关文章

asyncio并发编程

目录 asyncio并发编程 事件循环 基本使用 获取协程的返回值 回调 wait和gather task取消和子协程调用原理 task取消 子协程 其他方法 call_soon call_later call_at call_soon_threadsafe ThreadPollExecutor 和 asyncio完成阻塞io请求 asyncio发送http请求 asyncio同步和通信 同步 通信 asyncio并发编程 asyncio是Python3.4引入的一个用于异步IO的库,其主要功能

asyncio 并发编程(二)

Future 对象 future 表示还没有完成的工作结果.事件循环可以通过监视一个future 对象的状态来指示它已经完成.future 对象有几个状态: Pending:循环 Running:运行 Done:完成 Cancelled:取消 获取 Future 中的结果 创建future的时候,task为pending,事件循环调用执行的时候是running,调用完毕是done,如果需要停止事件循环,就需要先把task取消,状态为cancel. import asyncio def callb

Python高级编程和异步IO并发编程

Python高级编程和异步IO并发编程网盘地址:https://pan.baidu.com/s/1eB-BsUacBRhKxh7qXwndMQ 密码: tgba备用地址(腾讯微云):https://share.weiyun.com/5Z3x9V0 密码:7cdnb2 针对Python高级编程和异步IO并发编程,把每个Python高级知识点从起因到原理讲透的课程全网难寻 第1章 课程简介第2章 python中一切皆对象第3章 魔法函数第4章 深入类和对象第5章 自定义序列类第6章 深入python

Python并发编程之学习异步IO框架:asyncio 中篇(十)

大家好,并发编程 进入第十章.好了,今天的内容其实还挺多的,我准备了三天,到今天才整理完毕.希望大家看完,有所收获的,能给小明一个赞.这就是对小明最大的鼓励了.为了更好地衔接这一节,我们先来回顾一下上一节的内容. 上一节「」,我们首先介绍了,如何创建一个协程对象.主要有两种方法 通过async关键字, 通过@asyncio.coroutine 装饰函数. 然后有了协程对象,就需要一个事件循环容器来运行我们的协程.其主要的步骤有如下几点: 将协程对象转为task任务对象 定义一个事件循环对象容器用

[记录]Python高并发编程

========== ==多进程== ========== 要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回. 子进程永远返回0,而父进程返回子进程的ID.这样做的理由是,一个父进程可以fork出很多子进程,

python 闯关之路四(下)(并发编程与数据库编程) 并发编程重点

并发编程重点: 1 2 3 4 5 6 7 并发编程:线程.进程.队列.IO多路模型 操作系统工作原理介绍.线程.进程演化史.特点.区别.互斥锁.信号. 事件.join.GIL.进程间通信.管道.队列. 生产者消息者模型.异步模型.IO多路复用模型.select\poll\epoll 高性 能IO模型源码实例解析.高并发FTP server开发 1.请写一个包含10个线程的程序,主线程必须等待每一个子线程执行完成之后才结束执行,每一个子线程执行的时候都需要打印当前线程名.当前活跃线程数量: 1

asyncio--python3未来并发编程主流、充满野心的模块

介绍 asyncio是Python在3.5中正式引入的标准库,这是Python未来的并发编程的主流,非常重要的一个模块.有一个web框架叫sanic,就是基于asyncio,语法和flask类似,使用sanic可以达到匹配go语言的并发量,但无奈第三方组件太少. asyncio模块提供了使用协程构建并发应用的工具.threading模块通过应用线程实现并发,multiprocessing使用系统进程实现并发,asyncio使用一种单线程.单进程模式实现并发,应用的各个部分会彼此合作,在最优的时刻

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

VS C++ 并发编程

1.VS2012及以上版本,支持C++11 thread类的并发编程. 相关材料可以参考博客:http://www.cnblogs.com/rangozhang/p/4468754.html 2.但对其之前的版本,可采用以下方式,实现类成员函数创建子线程实现并发. 首先需实现线程类的run函数,故定义了线程类的头文件和其对应的函数实现,具体如图1,2所示: 图1 线程类的头文件 图2 线程类的实现文件 注意到继承的DerivedThread类,只需将并发执行的函数写在其对应的run()函数内即可