Asyncio.gather vs asyncio.wait


148

asyncio.gatherasyncio.waitdường như có cách sử dụng tương tự: Tôi có một loạt những thứ không đồng bộ mà tôi muốn thực thi / chờ đợi (không nhất thiết phải đợi một cái kết thúc trước khi cái tiếp theo bắt đầu). Họ sử dụng một cú pháp khác nhau và khác nhau ở một số chi tiết, nhưng có vẻ như tôi không có nhiều chức năng để có 2 chức năng có sự chồng chéo rất lớn về chức năng. Tôi đang thiếu gì?

Câu trả lời:


177

Mặc dù tương tự trong các trường hợp chung ("chạy và nhận kết quả cho nhiều tác vụ"), mỗi chức năng có một số chức năng cụ thể cho các trường hợp khác:

asyncio.gather()

Trả về một phiên bản Tương lai, cho phép nhóm các tác vụ ở mức cao:

import asyncio
from pprint import pprint

import random


async def coro(tag):
    print(">", tag)
    await asyncio.sleep(random.uniform(1, 3))
    print("<", tag)
    return tag


loop = asyncio.get_event_loop()

group1 = asyncio.gather(*[coro("group 1.{}".format(i)) for i in range(1, 6)])
group2 = asyncio.gather(*[coro("group 2.{}".format(i)) for i in range(1, 4)])
group3 = asyncio.gather(*[coro("group 3.{}".format(i)) for i in range(1, 10)])

all_groups = asyncio.gather(group1, group2, group3)

results = loop.run_until_complete(all_groups)

loop.close()

pprint(results)

Tất cả các nhiệm vụ trong một nhóm có thể bị hủy bằng cách gọi group2.cancel()hoặc thậm chí all_groups.cancel(). Xem thêm .gather(..., return_exceptions=True),

asyncio.wait()

Các hỗ trợ chờ được dừng sau khi hoàn thành nhiệm vụ đầu tiên hoặc sau khi hết thời gian chỉ định, cho phép các hoạt động ở mức độ chính xác thấp hơn:

import asyncio
import random


async def coro(tag):
    print(">", tag)
    await asyncio.sleep(random.uniform(0.5, 5))
    print("<", tag)
    return tag


loop = asyncio.get_event_loop()

tasks = [coro(i) for i in range(1, 11)]

print("Get first result:")
finished, unfinished = loop.run_until_complete(
    asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED))

for task in finished:
    print(task.result())
print("unfinished:", len(unfinished))

print("Get more results in 2 seconds:")
finished2, unfinished2 = loop.run_until_complete(
    asyncio.wait(unfinished, timeout=2))

for task in finished2:
    print(task.result())
print("unfinished2:", len(unfinished2))

print("Get all other results:")
finished3, unfinished3 = loop.run_until_complete(asyncio.wait(unfinished2))

for task in finished3:
    print(task.result())

loop.close()

4
"Biểu mẫu dấu hoa thị đơn (* args) được sử dụng để vượt qua danh sách đối số không có từ khóa, độ dài thay đổi và biểu mẫu dấu sao đôi được sử dụng để vượt qua danh sách đối số có độ dài thay đổi được từ khóa"
laycat

40

asyncio.waitlà cấp thấp hơn asyncio.gather.

Như tên cho thấy, asyncio.gatherchủ yếu tập trung vào việc thu thập kết quả. nó chờ đợi một loạt các tương lai và trả kết quả của họ theo một thứ tự nhất định.

asyncio.waitchỉ chờ đợi trong tương lai. và thay vì cung cấp cho bạn kết quả trực tiếp, nó cung cấp các nhiệm vụ đã hoàn thành và đang chờ xử lý. bạn phải thu thập các giá trị một cách thủ công.

Hơn nữa, bạn có thể chỉ định chờ tất cả các hợp đồng tương lai kết thúc hoặc chỉ là lần đầu tiên với wait.


Bạn nói : it waits on a bunch of futures and return their results in a given order. Điều gì xảy ra nếu tôi có 10000000000000 nhiệm vụ và tất cả chúng đều trả về dữ liệu lớn? tất cả kết quả sẽ làm cho bộ nhớ bùng nổ?
Kingname

@Kingname ..wat
Matt Tham gia

12

Tôi cũng nhận thấy rằng bạn có thể cung cấp một nhóm coroutines trong Wait () bằng cách chỉ định danh sách:

result=loop.run_until_complete(asyncio.wait([
        say('first hello', 2),
        say('second hello', 1),
        say('third hello', 4)
    ]))

Trong khi việc nhóm trong tập hợp () được thực hiện bằng cách chỉ định nhiều coroutines:

result=loop.run_until_complete(asyncio.gather(
        say('first hello', 2),
        say('second hello', 1),
        say('third hello', 4)
    ))

20
Danh sách cũng có thể được sử dụng với gather(), ví dụ:asyncio.gather(*task_list)
tehfink

1
Máy phát điện cũng vậy
Jab

Làm thế nào bạn có thể sử dụng tập hợp này mà không chặn phần còn lại của tập lệnh?
thebeancount
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.