1. 启动一个无返回值协程

    通过async关键字定义一个协程

    import sys
    import asyncio async def coroutine():
    print('运行协程') if sys.version_info >= (3, 7, 0):
    asyncio.run(coroutine())
    else:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(coroutine())
    loop.close()

    输出结果如下

    运行协程
  2. 启动一个有返回值协程

    import sys
    import asyncio async def coroutine():
    print('运行协程')
    return 'done!' if sys.version_info >= (3, 7, 0):
    result = asyncio.run(coroutine())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(coroutine())
    loop.close()
    print(result)

    输出结果如下

    运行协程
    done!
  3. 使用await关键字

    await关键字只能在一个协程内部使用

    await等待另一个协程任务结果,它不会阻塞事件循环,但会在阻塞当前协程的上下文

    import sys
    import asyncio async def coroutine():
    print('运行协程 调度asyncio.sleep协程任务')
    await asyncio.sleep(2)
    return 'done!' print('启动时间:', time.time())
    if sys.version_info >= (3, 7, 0):
    result = asyncio.run(coroutine())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(coroutine())
    loop.close()
    print(result)
    print('结束时间:', time.time())

    输出结果如下

    启动时间: 1598236154.90588
    运行协程 调度asyncio.sleep协程任务
    done!
    结束时间: 1598236156.9118028
  4. 回调函数: 迅速回调

    迅速回调是立即主动调用一个方法

    回调方法必然是一个普通函数

    回调通过事件循环loop提供的方法添加,它不会阻塞协程上下文

    同一个协程内的回调函数之间存在阻塞关系,不同协程内的回调函数之间无阻塞关系

    import sys
    import asyncio def callback(a, c=2):
    time.sleep(c)
    print(f"传入参数a={a}, c={c}, 时间{time.time()}") async def main():
    print(f'添加回调, 时间{time.time()}')
    loop = asyncio.get_running_loop()
    loop.call_soon(callback, 1)
    loop.call_soon(callback, 2, 0)
    print(f'协程结束, 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()
  5. 回调函数:延时回调

    延时回调可以指定在多久后执行回调函数

    延时回调的其他特性和迅速回调一致

    特别注意,如果事件循环内的协程已经运行结束,尚在等待调用的回调函数不会被调用

    import sys
    import asyncio def callback(a, c=3):
    time.sleep(c)
    print(f"传入参数a={a}, c={c}, 时间{time.time()}") async def main():
    print(f'添加回调, 时间{time.time()}')
    loop = asyncio.get_running_loop()
    loop.call_later(1, callback, 2, 0)
    loop.call_soon(callback, 1) print(f'协程结束, 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    添加回调, 时间1598237313.375363
    协程结束, 时间1598237313.375415
    传入参数a=1, c=3, 时间1598237316.376031
    传入参数a=2, c=0, 时间1598237316.376389

    解释说明,对于协程main,call_later和call_soon是不会阻塞协程上下文的,因此两个回调函数可以视为同时加入了事件循环的回调,其中回调callback(1)方法是立即调用,回调函数会sleep 3秒,而回调方法callback(2, 0)是在协程延时 1秒后调用,但回调函数之间是存在阻塞关系的,因此它会等待callback(1)先运行结束,然后判断是否满足了延时条件再执行。

  6. 回调函数:定时回调

    此处的指定时间并非系统时间戳,而是指事件循环创建的时间戳

    通过loop.time()获取事件循环时间戳

    import sys
    import asyncio def callback(a, loop, c=3):
    time.sleep(c)
    print(f"传入参数a={a}, c={c}, 时间{loop.time()}") async def main():
    loop = asyncio.get_running_loop()
    now = loop.time()
    print(f'事件循环时间戳{now}')
    loop.call_at(now + 4, callback, 2, loop, 1)
    loop.call_soon(callback, 1, loop)
    await asyncio.sleep(5)
    print(f'协程结束, 时间戳{loop.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()
  7. asyncio.Future对象

    Future的实例化对象可以认为是一个协程对象,它可以使用await关键字

    通过延时回调+Future可以模拟一个协程的逻辑

    即延时回调 ≈ 异步等待返回结果

    Future ≈ 非阻塞模型,它不会阻塞事件循环的其他协程

    import sys
    import asyncio def mark_done(future: asyncio.Future, result):
    print(f'标记future结束 时间{time.time()}')
    future.set_result(result) async def main():
    print(f'协程开始 时间{time.time()}')
    loop = asyncio.get_running_loop()
    future = asyncio.Future()
    loop.call_later(3, mark_done, future, 'done!')
    result = await future
    print(f'future结果 {result} 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598238858.6768472
    标记future结束 时间1598238861.678293
    future结果 done! 时间1598238861.678438
  8. Future回调

    Future的回调是在一个Future对象标记结束后运行的函数

    await会等待回调函数执行结束,即回调函数会在协程上下文阻塞

    import sys
    import asyncio def callback(future: asyncio.Future):
    # 基于Future的回调函数一定要接受一个Future对象
    print(f'Future回调被调用 时间{time.time()}')
    time.sleep(1) async def main():
    print(f'协程开始 时间{time.time()}')
    loop = asyncio.get_running_loop()
    future = asyncio.Future()
    future.add_done_callback(callback)
    loop.call_later(1, lambda future: future.set_result('done'), future)
    result = await future
    print(f'future结果 {result} 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598241100.534262
    Future回调被调用 时间1598241101.539032
    future结果 done 时间1598241102.5411909
  9. aysncio.Task对象

    Task对象在调用create_task会立即执行,它类似迅速回调

    asyncio.create_task是python3.7引入的高级api,3.7以下使用ensure_future方法

    与回调函数的区别:

    • 回调函数一定不是协程,而Task对象只能创建协程任务
    • 回调函数的传入参数直接通过添加回调的方法传入,而任务对象直接传入协程形参
    • 回调函数之间运行是阻塞的,而Task对象则是基于事件循环的标准协程

    在协程上下文中可以使用await关键字等待任务结果

    import sys
    import asyncio async def task_func(n):
    print(f'运行 task_func 时间{time.time()}')
    await asyncio.sleep(n)
    return 'task done!' async def main():
    loop = asyncio.get_running_loop()
    task = loop.create_task(task_func(3))
    result = await task
    print(f'task结果 {result} 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    运行 task_func  时间1598241581.334356
    task结果 task done! 时间1598241584.338337
  10. Task取消任务

    可以取消一个正在事件循环内运行的task对象

    Task和Future一样,支持通过add_done_callback添加回调函数

    import sys
    import asyncio async def task_func(n):
    print(f'运行 task_func 时间{time.time()}')
    await asyncio.sleep(n)
    return 'task done!' async def main():
    loop = asyncio.get_running_loop()
    task = asyncio.create_task(task_func(5))
    loop.call_later(3, lambda task: task.cancel(), task)
    # Task被取消 会抛出CancelledError异常
    try:
    result = await task
    print(f'task结果 {result} 时间{time.time()}')
    except asyncio.exceptions.CancelledError:
    print(f'task被取消了 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    运行 task_func  时间1598242256.3299708
    task被取消了 时间1598242259.335436
  11. 使用asyncio.ensure_future创建任务

    asyncio.ensure_future实现效果和asyncio.create_task一致

    import sys
    import asyncio async def task_func(n):
    print(f'运行 task_func 时间{time.time()}')
    await asyncio.sleep(n)
    return 'task done!' async def main():
    print(f'协程开始 时间{time.time()}')
    task = asyncio.ensure_future(task_func(2))
    result = await task
    print(f'task结果 {result} 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598249260.1346428
    运行 task_func 时间1598249260.1347158
    task结果 task done! 时间1598249262.137878
  12. asyncio.wait执行多个协程

    asyncio.wait接受一个协程列表/元组将其加入事件循环

    返回两个列表,分别包含已完成和正在执行的Future对象

    asyncio.wait 会阻塞协程上下文直至满足指定的条件(默认条件所有协程运行结束)

    wait支持设置一个超时时间,但在超时发生时不会取消可等待对象,但若事件循环结束时未完成则会抛出CancelledError异常。如果要超时主动取消,可用wait_for方法

    asyncio.wait 返回的结果集是按照事件循环中的任务完成顺序排列的,所以通常和原始任务顺序不同

    import sys
    import asyncio async def corn_sleep(n):
    try:
    await asyncio.sleep(n)
    except asyncio.exceptions.CancelledError:
    print(f'corn({n})超时取消! 时间{time.time()}')
    print(f'corn({n}) done! 时间{time.time()}')
    return f'corn({n}) done! 时间{time.time()}' async def main():
    print(f'协程开始 时间{time.time()}')
    tasks = [corn_sleep(i) for i in range(1, 6)]
    done, pending = await asyncio.wait(tasks, timeout=3)
    for task in done:
    pass
    # print(task.result())
    for task in pending:
    print(task.done())
    await asyncio.sleep(1)
    print(f'协程结束 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598253388.614105
    corn(1) done! 时间1598253389.6196852
    corn(2) done! 时间1598253390.6171541
    False
    False
    False
    corn(3) done! 时间1598253391.617078
    corn(4) done! 时间1598253392.617147
    协程结束 时间1598253392.617195
    corn(5)超时取消! 时间1598253392.6173718
    corn(5) done! 时间1598253392.6173818
  13. asyncio.gather执行多个协程

    gather方法和wait都可以执行多个协程,但输入和输出有所差异

    • 输出差异,gather保证了结果列表的顺序,它是严格遵循传入任务顺序的
    • 输入差异,wait方法接受的是一个协程列表,而gather是通过可变长参数传入协程方法的
    • wait支持超时设置,gather无法设置超时时间
    • wait返回两个列表,列表元素是Future对象,gather只返回done列表,列表元素是Future对象的result()结果
    import sys
    import asyncio async def corn_sleep(n):
    await asyncio.sleep(n)
    return f'corn({n}) done! 时间{time.time()}' async def main():
    print(f'协程开始 时间{time.time()}')
    tasks = [corn_sleep(i) for i in range(1, 6)]
    done = await asyncio.gather(*tasks)
    for result in done:
    print(result)
    print(f'协程结束 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598250547.5619462
    corn(1) done! 时间1598250548.567125
    corn(2) done! 时间1598250549.5660028
    corn(3) done! 时间1598250550.563731
    corn(4) done! 时间1598250551.566098
    corn(5) done! 时间1598250552.566897
    协程结束 时间1598250552.566983
  14. asyncio.as_completed执行多个协程

    as_completed方法功能同wait和gather都可以用于执行多个协程

    as_completed接受的是协程列表,返回的是一个迭代器,迭代元素为Future对象

    as_completed方法支持超时设置,但它会在协程上下文抛出asyncio.exceptions.TimeoutError错误

    as_completed方法返回结果集是无序的

    import sys
    import asyncio async def corn_sleep(n):
    await asyncio.sleep(n)
    return f'corn({n}) done! 时间{time.time()}' async def main():
    print(f'协程开始 时间{time.time()}')
    tasks = [corn_sleep(i) for i in range(1, 6)]
    for task in asyncio.as_completed(tasks, timeout=3.5):
    try:
    result = await task
    print(result)
    except asyncio.exceptions.TimeoutError:
    print(f'协程超时了 时间{time.time()}')
    break
    print(f'协程结束 时间{time.time()}') if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598251179.489662
    corn(1) done! 时间1598251180.493866
    corn(2) done! 时间1598251181.4911182
    corn(3) done! 时间1598251182.493823
    协程超时了 时间1598251182.991565
    协程结束 时间1598251182.991592
  15. 协程锁

    相比线程、进程锁,协程锁似乎应用场景不那么多,比如保存文件时?

    import sys
    import asyncio
    from functools import partial def callback(lock: asyncio.Lock):
    print(f'释放锁 时间{time.time()}')
    lock.release() async def corn1(x, loop, lock):
    async with lock:
    pass
    # 加锁,利用延迟回调1秒后解锁
    await lock.acquire()
    loop.call_later(1, callback, lock)
    return f'{x} done! 时间{time.time()}' async def main():
    loop = asyncio.get_running_loop()
    lock = asyncio.Lock()
    await lock.acquire()
    print(f'加锁 时间{time.time()}')
    loop.call_later(2, callback, lock)
    corn = partial(corn1, loop=loop, lock=lock)
    results = await asyncio.gather(corn(1), corn(2), corn(3))
    for result in results:
    print(result) if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    加锁 时间1598251855.600318
    释放锁 时间1598251857.6041799
    释放锁 时间1598251858.606617
    释放锁 时间1598251859.609798
    1 done! 时间1598251857.604349
    2 done! 时间1598251858.606834
    3 done! 时间1598251859.6099358
  16. Event 事件对象

    Event对象和Lock对象有一定的相似性,可用于同步操作

    Event对象提供一个状态标记位,它是一个布尔值,只用来判断状态

    import sys
    import asyncio def task_done(event: asyncio.Event):
    event.set() async def corn(event: asyncio.Event):
    await event.wait()
    print(f'corn done! 时间{time.time()}') async def main():
    print(f'协程开始 时间{time.time()}')
    event = asyncio.Event()
    loop = asyncio.get_running_loop()
    loop.call_later(2, task_done, event)
    await corn(event) if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    协程开始  时间1598252539.2691798
    corn done! 时间1598252541.273142
  17. Queue 协程队列

    与普通队列相比,协程队列有一个task_done方法,用于标记某一个任务结束,而join方法则会阻塞,直到满足从队列取出的个数等于task_done方法调用的次数

    import sys
    import asyncio async def producer(queue: asyncio.Queue):
    print('生产者 上班')
    for i in range(1, 6):
    await queue.put(f'产品({i})')
    await asyncio.sleep(2)
    await queue.put(None)
    await queue.join()
    print('生产者 打烊') async def consumer(x, queue: asyncio.Queue):
    print(f'消费者{x}号进场')
    while True:
    pt = await queue.get()
    queue.task_done()
    if pt is None:
    await queue.put(None)
    break
    else:
    print(f'{x}号 消费了 {pt}') async def main():
    loop = asyncio.get_running_loop()
    queue = asyncio.Queue(maxsize=3)
    loop.create_task(producer(queue))
    await asyncio.wait([consumer(i, queue) for i in range(3)]) if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    输出结果如下

    生产者 上班
    消费者2号进场
    2号 消费了 产品(1)
    消费者0号进场
    消费者1号进场
    2号 消费了 产品(2)
    0号 消费了 产品(3)
    1号 消费了 产品(4)
    2号 消费了 产品(5)
    生产者 下班
  18. asyncio.subprocess 异步调用子进程

    asyncio提供create_subprocess_exec和create_subprocess_shell方法

    前者可以调用任意程序,后者则通过shell命令行调用其他程序

    import sys
    import asyncio async def get_date():
    code = 'import datetime; print(datetime.datetime.now())'
    task1 = asyncio.create_subprocess_exec(
    sys.executable, '-c', code,
    stdout=asyncio.subprocess.PIPE
    )
    task2 = asyncio.create_subprocess_shell(
    'ls -all ~/Desktop', stdout=asyncio.subprocess.PIPE
    )
    results = await asyncio.gather(task1, task2)
    response = []
    for proc in results:
    data = await proc.stdout.read()
    line = data.decode('utf8').rstrip()
    response.append(line)
    return '\n'.join(response) date = asyncio.run(get_date())
    print(f"当前时间: {date}")

    输出结果如下

    当前时间: 2020-08-24 16:11:18.143943
    total 16
    drwxr-xr-x 3 sw staff 96 Apr 6 09:11 $RECYCLE.BIN
    drwx------@ 8 sw staff 256 Jun 18 10:52 .
    drwxr-xr-x+ 63 sw staff 2016 Aug 23 20:52 ..
    -rw-r--r--@ 1 sw staff 6148 Jul 22 17:54 .DS_Store
    -rw-r--r-- 1 sw staff 0 May 27 2019 .localized
    drwxr-xr-x 3 sw staff 96 Feb 3 2020 Don't Starve Together.app
    drwxr-xr-x 9 sw staff 288 May 3 18:24 HeavenMS
    drwxr-xr-x 3 sw staff 96 Sep 20 2019 Tomb Raider.app
  19. 网络通信-高级API

    asyncio封装了几个高级方法来快速实现网络通信

    • await asyncio.open_connection() 建立TCP连接
    • await asyncio.open_unix_connection() 建立Unix socket连接
    • await start_server() 启动TCP服务
    • await start_unix_server() 启动Unix socket服务
    • StreamReader 接收网络数据的高级async/await对象
    • StreamWriter 发送网络数据的高级async/await对象

    以搭建一个简单http服务器为例

    import sys
    import asyncio async def http_handle(render: asyncio.StreamReader,
    writer: asyncio.WriteTransport):
    """在asyncio.start_server传入该协程
    当一个tcp连接建立时就会调用该回调,并传入两个参数
    :param render: StreamReader对象
    :param writer: StreamWriter对象
    StreamReader和StreamWriter对象都是继承于Transport
    :return:
    """
    message = await render.read(1024)
    print(message.decode())
    writer.write(b'HTTP/1.1 200 OK\r\n\r\nHello Client!')
    writer.close() async def main():
    server = await asyncio.start_server(http_handle, '127.0.0.1', 8000)
    addr = server.sockets[0].getsockname()
    print(f'服务器启动 {addr}')
    async with server:
    await server.serve_forever() if sys.version_info >= (3, 7, 0):
    result = asyncio.run(main())
    else:
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(main())
    loop.close()

    浏览器打开http://127.0.0.1:8000 控制台输出结果如下

    GET / HTTP/1.1
    Host: 127.0.0.1:8000
    Connection: keep-alive
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    Sec-Fetch-Site: none
    Sec-Fetch-Mode: navigate
    Sec-Fetch-User: ?1
    Sec-Fetch-Dest: document
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9

    浏览器显示结果

    Hello Client!
  20. 网络通信-低级API

    案例19所用的方法是基于底层Transport和Protocol封装的结果

    Protocol协议类是通过重写一系列回调方法来处理网络请求

    Transport实例可以简单看作是对一个socket对象封装,实现了数据收发功能

    除了网络通信外,子进程(进程通信)也是通过协议回调来实现

    以一个tcp服务端为例,较常用的有4个回调函数

    • connection_made() 连接建立时被调用
    • connection_lost() 连接丢失或关闭时被调用
    • data_received() 接收到数据时被调用
    • eof_received() 接收到EOF时被调用

    以案例19的http服务端为例,实现相同效果

    import sys
    import asyncio class HttpProtocol(asyncio.Protocol):
    def __init__(self):
    """每个tcp连接建立时都会实例化这个类"""
    self.transport: asyncio.Transport = None def connection_made(self, transport: asyncio.Transport):
    """连接建立时被调用"""
    self.transport = transport def data_received(self, data):
    """接收数据时被调用"""
    print(data.decode())
    self.transport.write(b'HTTP/1.1 200 OK\r\n\r\nHello Client!')
    self.transport.close() loop = asyncio.get_event_loop()
    server = loop.create_server(HttpProtocol, '127.0.0.1', 8000)
    loop.run_until_complete(server)
    loop.run_forever()
  21. 信号处理

    事件循环能够支持添加信号来执行回调函数

    import signal
    import asyncio def ask_exit(sig_name: str, loop: asyncio.AbstractEventLoop):
    print("捕获信号 %s: exit" % sig_name)
    loop.stop() async def main():
    loop = asyncio.get_running_loop()
    for signame in {'SIGINT', 'SIGTERM'}:
    loop.add_signal_handler(
    getattr(signal, signame),
    partial(ask_exit, signame, loop)) await asyncio.sleep(3600) print("事件循环将在1小时后或者按下Ctrl+C停止")
    try:
    asyncio.run(main())
    except RuntimeError as e:
    if str(e) != 'Event loop stopped before Future completed.':
    raise

    输出结果如下

    事件循环将在1小时后或者按下Ctrl+C停止
    ^C捕获信号 SIGINT: exit

高频方法总结

  1. 回调和Task具有一定相似性,回调是函数,任务是协程

  2. 向事件循环非阻塞运行一个协程是创建一个任务,可以使用如下方法

    方法 传入 返回 备注
    asyncio.create_task 协程 Task对象 高层级api、Python3.7 +
    asyncio.ensure_future 协程 Task对象 高层级api
    loop.create_task 协程 Task对象 低层级api
  3. 向事件循环添加多个协程(使用await关键词才会实际添加运行),可使用如下方法

    方法 传入 返回 备注
    asyncio.wait 协程列表 done/pending列表
    元素是Future对象
    支持超时设置,结果无序
    asyncio.gather 变长参数 协程返回值组成的列表 返回结果列表有序
    asyncio.as_completed 协程列表 协程任务迭代器 通过for循环遍历获取任务结果
  4. 在unix平台,可以使用性能更好uvloop来替代asyncio默认的事件循环

    import uvloop
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

asyncio异步模块的21个协程编写实例的更多相关文章

  1. asyncio异步编程【含视频教程】

    不知道你是否发现,身边聊异步的人越来越多了,比如:FastAPI.Tornado.Sanic.Django 3.aiohttp等. 听说异步如何如何牛逼?性能如何吊炸天....但他到底是咋回事呢? 本 ...

  2. asyncio异步编程

    1. 协程 协程不是计算机提供,程序员认为创造 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术,其实就是一个线程实现代码块相互切换执行.例如: def func1(): ...

  3. 【Python3爬虫】使用异步协程编写爬虫

    一.基本概念 进程:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.进程是操作系统动态执行的基本单元. 线程:一个进程中包含若干线程,当然至少有一个线程,线程可以利用进程所拥有的资源.线程 ...

  4. asyncio异步IO--协程(Coroutine)与任务(Task)详解

    摘要:本文翻译自Coroutines and Tasks,主要介绍asyncio中用于处理协程和任务的方法和接口.在翻译过程中,译者在官方文档的基础上增加了部分样例代码和示意图表,以帮助读者对文档的理 ...

  5. Dojo初探之1:AMD规范,编写符合AMD规范(异步模块加载机制)的模块化JS(其中dojo采用1.11.2版本)

    一.AMD规范探索 1.AMD规范(即异步模块加载机制) 我们在接触js的时候,一般都是通过各种function来定义一些方法,让它们帮我们做一些事情,一个js可以包含很多个js,而这些functio ...

  6. 初识python异步模块Trio

    Trio翻译过来是三重奏的意思,它提供了更方便异步编程,是asyncio的更高级的封装. 它试图简化复杂的asyncio模块.使用起来比asyncio和Twisted要简单的同时,拥有其同样强大功能. ...

  7. python---爬虫相关性能(各个异步模块的使用,和自定义异步IO模块)

    一:线程池,进程池等相关文章了解 python---基础知识回顾(十)进程和线程(py2中自定义线程池和py3中的线程池使用) python---基础知识回顾(十)进程和线程(协程gevent:线程在 ...

  8. 【Python学习之九】asyncio—异步IO

    asyncio 这是python3.4引入的标准库,直接内置对异步IO的支持.asyncio的编程模型就是一个消息循环.从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程 ...

  9. asyncio 异步编程

    首先了解一下协程,协程的本质就是一条线程,多个任务在一条线程上来回切换,协程的所有切换都是基于用户,只有在用户级别才能感知到的 IO 才会用协程模块来规避,在 python 中主要使用的协程模块是 a ...

随机推荐

  1. JVM详解之:汇编角度理解本地变量的生命周期

    目录 简介 本地变量的生命周期 举例说明 优化的原因 总结 简介 java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢? 带着这个问题我们来看一下今 ...

  2. PHP EOF(heredoc) 使用说明

    PHP EOF(heredoc) 使用说明 PHP EOF(heredoc)是一种在命令行shell(如sh.csh.ksh.bash.PowerShell和zsh)和程序语言(像Perl.PHP.P ...

  3. 5.29 省选模拟赛 树的染色 dp 最优性优化

    LINK:树的染色 考场上以为这道题要爆蛋了 没想到 推出正解来了. 反正是先写了爆搜的 爆搜最近越写越熟练了 容易想到dp 容易设出状态 f[i][j]表示以i为根的子树内白色的值为j此时黑色的值怎 ...

  4. win10搭建基于docker的odoo开发环境

  5. 关于ORACLE索引的几种扫描方式

    ------------恢复内容开始------------ ------------恢复内容开始------------ 一条sql执行的效率因执行计划的差异而影响,经常说这条sql走索引了,那条s ...

  6. php操作mysql关于文件上传、存储

    php+前端+mysql实现文件上传并储存 我们都知道很多网站都需要上传文件,最普遍的就是图片上传,即是用户头像等等: 关于mysql+php实现文件查询,存储大致两个方式, 1.直接把文件写入mys ...

  7. AutoMapper 9.0的改造(续)

    上一篇有一个读者,有疑问,如何自动化注册Dto 我开篇,做了一个自动化注册的 public sealed class AutoInjectAttribute : Attribute { public ...

  8. 银弹谷零代码开发V百科|使用技巧:Vbase技巧二则之二

    银弹谷零代码开发V百科|使用技巧:Vbase技巧二则之二 结构树设置 Vbase系统提供机构树默认展开层级和加载模式的设置. sa账号登录,默认密码8. 打开机构与权限管理—机构初始化设置菜单,选择“ ...

  9. GitLab 系列文章

    GitLab 系列文章 记录 GitLab 的相关文章 列表 Docker 搭建 GitLab GitLab CI/CD 配置 GitLab 配置模板 访问 GitLab 数据库 GitLab 转让所 ...

  10. image classification backbone 汇总分析

    下面是一个list,可以详细看一下 image_classification = [['name','top1_acc','top5_acc','size'],['FixEfficientNet-L2 ...