python coroutine learning

1. What is coroutine and how to implement it

1.1 Coroutine

        Also known as micro-threads, fibers, also known as user-level threads, they complete multiple tasks without opening up threads, that is, they complete multiple tasks in a single thread, and multiple tasks are executed alternately in a certain order.

1.2 Implementation method

  1. greenlet, early module;
  2. yield keyword;
  3. asyncio decorator (py3.4);
  4. async, await keywords (py3.5) (recommended);

2. Examples of implementation methods

2.1 greenlet

from greenlet import greenlet
def func1():
    print(1)        # 第1步: 输出 1
    gr2.switch()    # 第3步: 切换到 func2 函数
    print(2)        # 第6步: 输出 2
    gr2.switch()    # 第7步: 切换到 func2 函数,从上一次执行的位置继续向后执行

def func2() :
    print(3)        # 第4步: 输出 3
    grl.switch()    # 第5步: 切换到 func1 函数,从上一次执行的位置继续向后执行
    print(4)        # 第8步: 输出 4

gr1 = greenTet(func1)
gr2 = greenTet(func2)

grl.switch()        # 第1步: 去执行 func1 函数

2.2 yield keyword

import time

def work1():
    while True:
        print("----work1---")
        yield
        time.sleep(0.5)

def work2():
    while True:
        print("----work2---")
        yield
        time.sleep(0.5)

def main():
    w1 = work1()
    w2 = work2()
    while True:
        next(w1)
        next(w2)

if __name__ == "__main__":
    main()

2.3 asyncio decorator (py3.4)

import asyncio
@asyncio.coroutine
def func1():
    print(1)
    yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(2)

@asyncio.coroutine
def func2():
    print(3)
    yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(4)

tasks = [
    asyncio.ensure_future( func1()),
    asyncio.ensure_future( func2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

2.4 async, await keywords (py3.5)

import asyncio

async def func1():
    print(1)
    await asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(2)

async def func2():
    print(3)
    await asyncio.sleep(2)  # 遇到IO耗时操作,自动化切换到tasks中的其他任务
    print(4)

tasks = [
    asyncio.ensure_future( func1()),
    asyncio.ensure_future( func2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

3. The meaning of coroutine

        If a thread encounters IO waiting time (such as local disk data reading and network data request), the thread will not wait and use the idle time to do other things.

        Case: Download three pictures (network IO)

Ordinary way (that is, synchronous programming):

import requests

def download_image(url):
    print("开始下载:", url)  #发送网络请求,下载图片
    response = requests.get(url)
    print("下载完成")
    # 图片保存到本地文件
    file_name = url.rsplit('_')[-1]
    with open(file_name, mode='wb') as file_object:
        file_object.write(response.content)


if __name__ == "_main__":
    url_list = [
    "https://www3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar_ChsEe12AX06A0OH_AAFocMs8nzu621.jpg",
    "https://www2.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar_chcCSV2BBICAUntfAADjJFd6800429.jpg",
    "https://www3.autoimg.cn/newsdfs/g26/M0B/3C/65/120x90_0_autohomecar_ChcCP12BFCmAIO83AAGq7vK0sGY193.jpg"
    ]
    for item in url_list:
        download_image(item)

Coroutine solution (that is, asynchronous programming):

import aiohttp
import asyncio

async def fetch(session, url):
    print("发送请求:", url)
    async with session.get(url, verify_ssl=False) as response:
        content = await response.content.read()
        file_name = url.rsplit('_')[-1]
        with open(file_name, mode="wb") as file_object:
            file_object.write(content)

async def main():
    async with aiohttp.ClientSession() as session:
        url_list =["https://ww3.autoimg.cn/newsdfs/g26/M02/35/A9/120x90_0_autohomecar_ChsEe2AX06A00H_AAFOCHs8nzU621.jpg",
                   "https://ww2.autoimg.cn/newsdfs/g30/M01/3C/E2/120x90_0_autohomecar_ChcCSV288ICAUntfAADjJFd6800429.jpg",
                   "https://wm3.automg,cn/newsdfs/g26/M0B/3C/65/120x90_0_autohomecar_ChcCP12BFCmA083AAGq7VK0sGY193.jpg"
        ]
        tasks = [asyncio.create_task(fetch(session, url)) for url in url_list]
        await asyncio.wait(tasks)

if __name__ == "__main__":
    asyncio.run(main())

4. Get started quickly

4.1 Basic syntax       

        Coroutine function, modified with async when defining the function, as follows

async def func():
    pass
result = func()  # 获取协程对象

        Note that when executing a coroutine function to create a coroutine object, the code inside the function will not be executed; if you want to run the code inside the coroutine function, you must hand over the coroutine object to the event loop for processing. as follows

import asyncio

async def func():
    print("快来搞我吧!")

result = func()

# ss1oop = asyncio.get_event_loop()
# ss1oop.run_until_complete( result )

asyncio.run( result ) # python3.7

4.2 await

 Example one:

        await + awaitable object (coroutine object, Future, Task object)

import asyncio

async def func():
    print("快来搞我吧!")
    response = await asyncio.sleep(2)
    print("结束", response)

result = func()

ss1oop = asyncio.get_event_loop()
ss1oop.run_until_complete( result )

#asyncio.run( result ) # python3.7

 

4.3 Task object

        Add multiple tasks in the event loop.

        Tasks are used to concurrently schedule coroutines. Task objects are created through asyncio.create_task (coroutine object), which allows coroutines to join the event loop and wait to be scheduled for execution. In addition to using the asyncio.create_task() function, you can also use the low-level loop.create_task0 or ensure_future() functions. It is not recommended to instantiate Task objects manually. Note: The
        asyncio.create_task() function was added in Python 3.7. In Python 3.7 Previously, you could use the low-level asyncio.ensure_future() function instead.

Example one:

 Example 2:

 4.4 asyncio.Future object

        Task inherits Future, and the processing of await results inside the Task object is based on the Future object.

Example one:

Example two:

 4.5 concurrent.futures.Future object

        Objects used when implementing asynchronous operations using thread pools and process pools.

 

Guess you like

Origin blog.csdn.net/qq_31112205/article/details/130015052