Coroutine và nhiệm vụ

Phần này trình bày các API asyncio cấp cao để hoạt động với coroutine và Task.

Coroutine

Source code: Lib/asyncio/coroutines.py


Coroutines được khai báo bằng cú pháp async/await là cách viết ứng dụng asyncio ưa thích. Ví dụ: đoạn mã sau in "hello", đợi 1 giây rồi in "world":

>>> nhập asyncio

>>> async def main():
... in('xin chào')
... đang chờ asyncio.sleep(1)
... in('thế giới')

>>> asyncio.run(main())
xin chào
thế giới

Lưu ý rằng việc chỉ gọi một coroutine sẽ không lên lịch thực thi nó:

>>> chính()
<đối tượng coroutine chính tại 0x1053bb7c8>

Để thực sự chạy một coroutine, asyncio cung cấp các cơ chế sau:

  • Hàm asyncio.run() để chạy hàm "main()" của điểm nhập cấp cao nhất (xem ví dụ trên.)

  • Đang chờ coroutine. Đoạn mã sau sẽ in "hello" sau khi đợi 1 giây và sau đó in "world" sau khi đợi another 2 giây

    nhập asyncio
    thời gian nhập khẩu
    
    async def say_after(delay, what):
        đang chờ asyncio.sleep(delay)
        in (cái )
    
    async def main():
        print(f"bắt đầu lúc {time.strftime('%X')}")
    
        đang chờ say_after(1, 'xin chào')
        đang chờ say_after(2, 'thế giới')
    
        print(f"hoàn thành lúc {time.strftime('%X')}")
    
    asyncio.run(chính())
    

    Sản lượng dự kiến:

    bắt đầu lúc 17:13:52
    xin chào
    thế giới
    kết thúc lúc 17:13:55
    
  • Hàm asyncio.create_task() để chạy đồng thời các coroutine dưới dạng asyncio Tasks.

    Hãy sửa đổi ví dụ trên và chạy hai coroutine say_after concurrently:

    async def main():
        task1 = asyncio.create_task(
            say_after(1, 'xin chào'))
    
        task2 = asyncio.create_task(
            say_after(2, 'thế giới'))
    
        print(f"bắt đầu lúc {time.strftime('%X')}")
    
        # Wait cho đến khi cả hai nhiệm vụ được hoàn thành (nên mất
        # around 2 giây.)
        đang chờ nhiệm vụ 1
        đang chờ nhiệm vụ2
    
        print(f"hoàn thành lúc {time.strftime('%X')}")
    

    Lưu ý rằng kết quả dự kiến hiện cho thấy đoạn mã chạy nhanh hơn 1 giây so với trước đây:

    bắt đầu lúc 17:14:32
    xin chào
    thế giới
    kết thúc lúc 17:14:34
    
  • Lớp asyncio.TaskGroup cung cấp một giải pháp thay thế hiện đại hơn cho create_task(). Sử dụng API này, ví dụ cuối cùng trở thành:

    async def main():
        không đồng bộ với asyncio.TaskGroup() dưới dạng tg:
            task1 = tg.create_task(
                say_after(1, 'xin chào'))
    
            task2 = tg.create_task(
                say_after(2, 'thế giới'))
    
            print(f"bắt đầu lúc {time.strftime('%X')}")
    
        # The chờ đợi ẩn khi trình quản lý bối cảnh thoát.
    
        print(f"hoàn thành lúc {time.strftime('%X')}")
    

    Thời gian và đầu ra phải giống như phiên bản trước.

    Added in version 3.11: asyncio.TaskGroup.

Đang chờ

Chúng ta nói rằng một đối tượng là đối tượng awaitable nếu nó có thể được sử dụng trong biểu thức await. Nhiều API asyncio được thiết kế để chấp nhận các sản phẩm có thể chờ được.

Có ba loại đối tượng awaitable chính: coroutines, TasksFutures.

Coroutine

Các coroutine Python là awaitables và do đó có thể chờ đợi từ các coroutine khác:

nhập asyncio

async def lồng nhau():
    trở lại 42

async def main():
    # Nothing xảy ra nếu chúng ta chỉ gọi "nested()".
    Đối tượng coroutine # A được tạo nhưng không được chờ đợi,
    # so nó *won't run at all*.
    Nested() # will đưa ra "RuntimeWarning".

    # Let hãy làm điều đó theo cách khác ngay bây giờ và chờ đợi:
    print(await Nested()) # will print "42".

asyncio.run(chính())

Quan trọng

Trong tài liệu này, thuật ngữ "coroutine" có thể được sử dụng cho hai khái niệm có liên quan chặt chẽ với nhau:

  • coroutine function: hàm async def;

  • a coroutine object: một đối tượng được trả về bằng cách gọi coroutine function.

Nhiệm vụ

Tasks được dùng để lên lịch cho coroutine concurrently.

Khi một coroutine được gói vào một Task với các chức năng như asyncio.create_task(), coroutine sẽ tự động được lên lịch để chạy sớm:

nhập asyncio

async def lồng nhau():
    trở lại 42

async def main():
    # Schedule lồng nhau() sẽ sớm chạy đồng thời
    # with "chính()".
    nhiệm vụ = asyncio.create_task(nested())

    # "task" bây giờ có thể được sử dụng để hủy "nested()" hoặc
    # can chỉ cần đợi cho đến khi nó hoàn thành:
    chờ đợi nhiệm vụ

asyncio.run(chính())

Hợp đồng tương lai

Future là một đối tượng low-level đặc biệt có thể chờ đợi, đại diện cho eventual result của một hoạt động không đồng bộ.

Khi một đối tượng Tương lai là awaited, điều đó có nghĩa là coroutine sẽ đợi cho đến khi Tương lai được giải quyết ở một nơi khác.

Các đối tượng trong tương lai trong asyncio là cần thiết để cho phép sử dụng mã dựa trên lệnh gọi lại với async/await.

Thông thường there is no need để tạo các đối tượng Tương lai ở mã cấp ứng dụng.

Các đối tượng trong tương lai, đôi khi được các thư viện và một số API asyncio hiển thị, có thể được chờ đợi

async def main():
    đang chờ hàm_that_returns_a_future_object()

    # this cũng hợp lệ:
    đang chờ asyncio.gather(
        function_that_returns_a_future_object(),
        some_python_coroutine()
    )

Một ví dụ điển hình về hàm cấp thấp trả về đối tượng Tương lai là loop.run_in_executor().

Tạo nhiệm vụ

Source code: Lib/asyncio/tasks.py


asyncio.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)

Gói coro coroutine vào Task và lên lịch thực hiện. Trả về đối tượng Nhiệm vụ.

Chữ ký hàm đầy đủ phần lớn giống với chữ ký của hàm tạo Task (hoặc nhà máy) - tất cả các đối số từ khóa cho hàm này đều được chuyển qua giao diện đó.

Đối số context chỉ có từ khóa tùy chọn cho phép chỉ định một contextvars.Context tùy chỉnh để coro chạy vào. Bản sao ngữ cảnh hiện tại được tạo khi không cung cấp context.

Đối số eager_start chỉ có từ khóa tùy chọn cho phép chỉ định xem tác vụ sẽ được thực thi một cách háo hức trong khi gọi tới create_task hay được lên lịch sau. Nếu eager_start không được thông qua, chế độ do loop.set_task_factory() đặt sẽ được sử dụng.

Tác vụ được thực thi trong vòng lặp được trả về bởi get_running_loop(), RuntimeError được nâng lên nếu không có vòng lặp đang chạy trong luồng hiện tại.

Ghi chú

asyncio.TaskGroup.create_task() là một giải pháp thay thế mới tận dụng tính đồng thời của cấu trúc; nó cho phép chờ đợi một nhóm nhiệm vụ liên quan với sự đảm bảo an toàn mạnh mẽ.

Quan trọng

Lưu tham chiếu đến kết quả của hàm này để tránh tác vụ biến mất khi đang thực thi. Vòng lặp sự kiện chỉ giữ các tham chiếu yếu đến các tác vụ. Một tác vụ không được tham chiếu ở nơi khác có thể được thu gom rác bất cứ lúc nào, ngay cả trước khi nó được thực hiện. Để có các tác vụ nền "bắn và quên" đáng tin cậy, hãy tập hợp chúng vào bộ sưu tập:

nền_tasks = set()

cho tôi trong phạm vi (10):
    nhiệm vụ = asyncio.create_task(some_coro(param=i))

    nhiệm vụ # Add vào tập hợp. Điều này tạo ra một tài liệu tham khảo mạnh mẽ.
    nền_tác vụ.add (tác vụ)

    # To ngăn việc lưu giữ các tham chiếu đến các nhiệm vụ đã hoàn thành mãi mãi,
    # make mỗi tác vụ sẽ xóa tham chiếu riêng của nó khỏi tập hợp sau
    # completion:
    task.add_done_callback(background_tasks.discard)

Added in version 3.7.

Thay đổi trong phiên bản 3.8: Đã thêm tham số name.

Thay đổi trong phiên bản 3.11: Đã thêm tham số context.

Thay đổi trong phiên bản 3.14: Đã thêm tham số eager_start bằng cách chuyển tất cả kwargs.

Hủy nhiệm vụ

Nhiệm vụ có thể được hủy bỏ một cách dễ dàng và an toàn. Khi một nhiệm vụ bị hủy, asyncio.CancelledError sẽ được nâng lên trong nhiệm vụ ở cơ hội tiếp theo.

Các coroutine nên sử dụng khối try/finally để thực hiện logic dọn dẹp một cách mạnh mẽ. Trong trường hợp asyncio.CancelledError bị bắt rõ ràng, thông thường nó sẽ được phổ biến khi quá trình dọn dẹp hoàn tất. asyncio.CancelledError trực tiếp phân lớp BaseException nên hầu hết mã sẽ không cần phải biết về nó.

Các thành phần asyncio cho phép hoạt động đồng thời có cấu trúc, như asyncio.TaskGroupasyncio.timeout(), được triển khai bằng cách hủy nội bộ và có thể hoạt động sai nếu một coroutine nuốt asyncio.CancelledError. Tương tự, mã người dùng thường không nên gọi uncancel. Tuy nhiên, trong trường hợp thực sự muốn loại bỏ asyncio.CancelledError, cũng cần phải gọi uncancel() để loại bỏ hoàn toàn trạng thái hủy.

Nhóm nhiệm vụ

Các nhóm nhiệm vụ kết hợp việc tạo nhiệm vụ API với một cách thuận tiện và đáng tin cậy để chờ tất cả các nhiệm vụ trong nhóm hoàn thành.

class asyncio.TaskGroup

Một asynchronous context manager đang nắm giữ một nhóm nhiệm vụ. Nhiệm vụ có thể được thêm vào nhóm bằng create_task(). Tất cả các tác vụ được chờ đợi khi trình quản lý bối cảnh thoát.

Added in version 3.11.

create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)

Tạo một nhiệm vụ trong nhóm nhiệm vụ này. Chữ ký khớp với chữ ký của asyncio.create_task(). Nếu nhóm nhiệm vụ không hoạt động (ví dụ: chưa được nhập, đã hoàn thành hoặc đang trong quá trình tắt), chúng tôi sẽ đóng coro đã cho.

Thay đổi trong phiên bản 3.13: Đóng coroutine đã cho nếu nhóm tác vụ không hoạt động.

Thay đổi trong phiên bản 3.14: Chuyển tất cả kwargs sang loop.create_task()

Ví dụ:

async def main():
    không đồng bộ với asyncio.TaskGroup() dưới dạng tg:
        task1 = tg.create_task(some_coro(...))
        task2 = tg.create_task(another_coro(...))
    print(f"Cả hai tác vụ hiện đã hoàn thành: {task1.result()}, {task2.result()}")

Câu lệnh async with sẽ đợi tất cả các task trong nhóm kết thúc. Trong khi chờ đợi, các tác vụ mới vẫn có thể được thêm vào nhóm (ví dụ: bằng cách chuyển tg vào một trong các coroutine và gọi tg.create_task() trong coroutine đó). Khi nhiệm vụ cuối cùng đã hoàn thành và khối async with được thoát ra, không có nhiệm vụ mới nào có thể được thêm vào nhóm.

Lần đầu tiên bất kỳ nhiệm vụ nào thuộc nhóm không thành công với ngoại lệ không phải là asyncio.CancelledError, các nhiệm vụ còn lại trong nhóm sẽ bị hủy. Sau đó, không thể thêm nhiệm vụ nào nữa vào nhóm. Tại thời điểm này, nếu phần nội dung của câu lệnh async with vẫn hoạt động (tức là __aexit__() chưa được gọi), thì tác vụ chứa trực tiếp câu lệnh async with cũng bị hủy. Kết quả asyncio.CancelledError sẽ làm gián đoạn await, nhưng nó sẽ không thoát ra khỏi câu lệnh async with chứa.

Sau khi tất cả tác vụ đã hoàn tất, nếu bất kỳ tác vụ nào không thành công với ngoại lệ không phải là asyncio.CancelledError, thì những ngoại lệ đó sẽ được kết hợp trong ExceptionGroup hoặc BaseExceptionGroup (nếu thích hợp; xem tài liệu của chúng) sau đó sẽ được đưa ra.

Hai trường hợp ngoại lệ cơ bản được xử lý đặc biệt: Nếu bất kỳ tác vụ nào không thành công với KeyboardInterrupt hoặc SystemExit, nhóm tác vụ vẫn hủy các tác vụ còn lại và chờ chúng, nhưng sau đó KeyboardInterrupt hoặc SystemExit ban đầu sẽ được kích hoạt lại thay vì ExceptionGroup hoặc BaseExceptionGroup.

Nếu phần nội dung của câu lệnh async with thoát ra với một ngoại lệ (vì vậy __aexit__() được gọi với một bộ ngoại lệ), thì điều này được xử lý giống như khi một trong các tác vụ không thành công: các tác vụ còn lại bị hủy và sau đó được chờ đợi, đồng thời các ngoại lệ không bị hủy sẽ được nhóm thành một nhóm ngoại lệ và được nâng lên. Ngoại lệ được chuyển vào __aexit__(), trừ khi đó là asyncio.CancelledError, cũng được bao gồm trong nhóm ngoại lệ. Trường hợp đặc biệt tương tự được thực hiện cho KeyboardInterruptSystemExit như trong đoạn trước.

Các nhóm nhiệm vụ phải cẩn thận để không nhầm lẫn việc hủy bỏ nội bộ được sử dụng để "đánh thức" __aexit__() của họ với các yêu cầu hủy đối với nhiệm vụ mà họ đang thực hiện do các bên khác thực hiện. Đặc biệt, khi một nhóm nhiệm vụ được lồng vào một nhóm nhiệm vụ khác về mặt cú pháp và cả hai đều gặp phải một ngoại lệ ở một trong các nhiệm vụ con của chúng cùng một lúc thì nhóm nhiệm vụ bên trong sẽ xử lý các ngoại lệ của nó, sau đó nhóm nhiệm vụ bên ngoài sẽ nhận được một lần hủy khác và xử lý các ngoại lệ của chính nó.

Trong trường hợp một nhóm nhiệm vụ bị hủy bên ngoài và cũng phải tăng ExceptionGroup, nó sẽ gọi phương thức cancel() của nhiệm vụ mẹ. Điều này đảm bảo rằng asyncio.CancelledError sẽ được nâng lên ở await tiếp theo, do đó việc hủy không bị mất.

Các nhóm nhiệm vụ bảo toàn số lần hủy được báo cáo bởi asyncio.Task.cancelling().

Thay đổi trong phiên bản 3.13: Cải thiện việc xử lý các lần hủy nội bộ và bên ngoài đồng thời và bảo toàn số lượng hủy chính xác.

Chấm dứt một nhóm nhiệm vụ

Mặc dù việc chấm dứt một nhóm nhiệm vụ không được thư viện chuẩn hỗ trợ nguyên bản, nhưng việc chấm dứt có thể đạt được bằng cách thêm một nhiệm vụ tăng ngoại lệ vào nhóm nhiệm vụ và bỏ qua ngoại lệ đã nêu:

nhập asyncio
từ nhóm tác vụ nhập asyncio

lớp Chấm dứtTaskGroup (Ngoại lệ):
    """Ngoại lệ được nêu ra để chấm dứt một nhóm nhiệm vụ."""

async def Force_terminate_task_group():
    """Được sử dụng để buộc chấm dứt một nhóm nhiệm vụ."""
    tăng Chấm dứtTaskGroup()

công việc không đồng bộ (task_id, sleep_time):
    print(f'Task {task_id}: start')
    đang chờ asyncio.sleep(sleep_time)
    print(f'Task {task_id}: xong')

async def main():
    thử:
        không đồng bộ với TaskGroup() dưới dạng nhóm:
            # spawn một số nhiệm vụ
            group.create_task(job(1, 0.5))
            group.create_task(job(2, 1.5))
            # sleep trong 1 giây
            đang chờ asyncio.sleep(1)
            # add một nhiệm vụ tăng ngoại lệ để buộc nhóm chấm dứt
            nhóm.create_task(force_terminate_task_group())
    ngoại trừ* Chấm dứtTaskGroup:
        vượt qua

asyncio.run(chính())

Sản lượng dự kiến:

Nhiệm vụ 1: bắt đầu
Nhiệm vụ 2: bắt đầu
Nhiệm vụ 1: đã xong

đang ngủ

async asyncio.sleep(delay, result=None)

Chặn trong delay giây.

Nếu result được cung cấp, nó sẽ được trả về cho người gọi khi coroutine hoàn tất.

sleep() luôn tạm dừng tác vụ hiện tại, cho phép các tác vụ khác chạy.

Đặt độ trễ thành 0 sẽ cung cấp đường dẫn được tối ưu hóa để cho phép các tác vụ khác chạy. Điều này có thể được sử dụng bởi các hàm chạy dài để tránh chặn vòng lặp sự kiện trong toàn bộ thời gian của lệnh gọi hàm.

Ví dụ về coroutine hiển thị ngày hiện tại mỗi giây trong 5 giây:

nhập asyncio
nhập ngày giờ dưới dạng dt

không đồng bộ hiển thị_date():
    vòng lặp = asyncio.get_running_loop()
    end_time = loop.time() + 5.0
    trong khi Đúng:
        in(dt.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            phá vỡ
        đang chờ asyncio.sleep(1)

asyncio.run(display_date())

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Thay đổi trong phiên bản 3.13: Tăng ValueError nếu delaynan.

Chạy các tác vụ đồng thời

awaitable asyncio.gather(*aws, return_exceptions=False)

Chạy awaitable objects theo trình tự aws concurrently.

Nếu bất kỳ thứ gì có thể chờ đợi trong aws là một coroutine thì nó sẽ tự động được lên lịch dưới dạng Nhiệm vụ.

Nếu tất cả các mục chờ được hoàn thành thành công thì kết quả là danh sách tổng hợp các giá trị được trả về. Thứ tự của các giá trị kết quả tương ứng với thứ tự của các sản phẩm đang chờ trong aws.

Nếu return_exceptionsFalse (mặc định), ngoại lệ được nêu ra đầu tiên sẽ ngay lập tức được truyền tới tác vụ đang chờ trên gather(). Các sản phẩm chờ đợi khác trong chuỗi aws won't be cancelled và sẽ tiếp tục chạy.

Nếu return_exceptionsTrue, các trường hợp ngoại lệ sẽ được xử lý giống như kết quả thành công và được tổng hợp trong danh sách kết quả.

Nếu gather()cancelled, tất cả các sản phẩm chờ được gửi (chưa hoàn thành) cũng là cancelled.

Nếu bất kỳ Nhiệm vụ hoặc Tương lai nào từ chuỗi awscancelled, thì nhiệm vụ đó sẽ được xử lý như thể nó đã tăng CancelledError -- lệnh gọi gather() bị hủy trong trường hợp này. Điều này nhằm ngăn chặn việc hủy bỏ một Nhiệm vụ/Tương lai đã gửi để khiến các Nhiệm vụ/Tương lai khác cũng bị hủy.

Ghi chú

Một giải pháp thay thế mới để tạo và chạy các tác vụ đồng thời và chờ chúng hoàn thành là asyncio.TaskGroup. TaskGroup cung cấp các đảm bảo an toàn mạnh mẽ hơn gather trong việc lên lịch lồng các nhiệm vụ phụ: nếu một nhiệm vụ (hoặc một nhiệm vụ phụ, một nhiệm vụ được lên lịch bởi một nhiệm vụ) đưa ra một ngoại lệ, thì TaskGroup sẽ, trong khi gather sẽ không hủy các nhiệm vụ đã lên lịch còn lại.

Ví dụ:

nhập asyncio

async def giai thừa (tên, số):
    f = 1
    cho i trong phạm vi (2, số + 1):
        print(f"Nhiệm vụ {name}: Tính giai thừa({number}), hiện tại i={i}...")
        đang chờ asyncio.sleep(1)
        f *= tôi
    print(f"Nhiệm vụ {name}: giai thừa({number}) = {f}")
    trở lại f

async def main():
    # Schedule ba cuộc gọi *concurrently*:
    L = đang chờ asyncio.gather(
        giai thừa("A", 2),
        giai thừa("B", 3),
        giai thừa("C", 4),
    )
    in(L)

asyncio.run(chính())

đầu ra # Expected:
#
#     Task A: Tính giai thừa(2), hiện tại i=2...
#     Task B: Tính giai thừa(3), hiện tại i=2...
#     Task C: Tính giai thừa(4), hiện tại i=2...
#     Task A: giai thừa(2) = 2
#     Task B: Tính giai thừa(3), hiện tại i=3...
#     Task C: Tính giai thừa(4), hiện tại i=3...
#     Task B: giai thừa(3) = 6
#     Task C: Tính giai thừa(4), hiện tại i=4...
#     Task C: giai thừa(4) = 24
# [2, 6, 24]

Ghi chú

Nếu return_exceptions sai, việc hủy thu thập() sau khi được đánh dấu là xong sẽ không hủy bất kỳ sản phẩm đang chờ nào đã gửi. Ví dụ: việc thu thập có thể được đánh dấu là hoàn tất sau khi truyền một ngoại lệ cho người gọi, do đó, việc gọi gather.cancel() sau khi bắt được một ngoại lệ (được đưa ra bởi một trong các đối tượng có thể chờ) từ việc thu thập sẽ không hủy bất kỳ đối tượng có thể chờ nào khác.

Thay đổi trong phiên bản 3.7: Nếu gather bị hủy thì việc hủy sẽ được truyền đi bất kể return_exceptions.

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Sắp loại bỏ từ phiên bản 3.10: Cảnh báo không dùng nữa được đưa ra nếu không cung cấp đối số vị trí hoặc không phải tất cả đối số vị trí đều là đối tượng giống Tương lai và không có vòng lặp sự kiện đang chạy.

Nhà máy nhiệm vụ háo hức

asyncio.eager_task_factory(loop, coro, *, name=None, context=None)

Một nhà máy nhiệm vụ để thực hiện nhiệm vụ háo hức.

Khi sử dụng nhà máy này (thông qua loop.set_task_factory(asyncio.eager_task_factory)), coroutine bắt đầu thực thi đồng bộ trong quá trình xây dựng Task. Nhiệm vụ chỉ được lên lịch trên vòng lặp sự kiện nếu chúng bị chặn. Đây có thể là một cải tiến hiệu suất vì tránh được chi phí lên lịch vòng lặp đối với các coroutine hoàn thành đồng bộ.

Một ví dụ phổ biến cho thấy điều này có lợi là các coroutine sử dụng bộ nhớ đệm hoặc ghi nhớ để tránh thao tác I/O thực tế khi có thể.

Ghi chú

Việc thực thi coroutine ngay lập tức là một sự thay đổi về ngữ nghĩa. Nếu coroutine trả về hoặc tăng lên thì tác vụ sẽ không bao giờ được lên lịch cho vòng lặp sự kiện. Nếu việc thực thi coroutine chặn thì tác vụ sẽ được lên lịch vào vòng lặp sự kiện. Thay đổi này có thể giới thiệu những thay đổi về hành vi đối với các ứng dụng hiện có. Ví dụ: thứ tự thực hiện tác vụ của ứng dụng có thể thay đổi.

Added in version 3.12.

asyncio.create_eager_task_factory(custom_task_constructor)

Tạo một nhà máy sản xuất nhiệm vụ háo hức, tương tự như eager_task_factory(), sử dụng custom_task_constructor được cung cấp khi tạo một nhiệm vụ mới thay vì Task mặc định.

custom_task_constructor phải là callable có chữ ký trùng với chữ ký của Task.__init__. Có thể gọi được phải trả về một đối tượng tương thích với asyncio.Task.

Hàm này trả về một callable dự định được sử dụng làm nhà máy tác vụ của vòng lặp sự kiện thông qua loop.set_task_factory(factory)).

Added in version 3.12.

Bảo vệ khỏi việc hủy bỏ

awaitable asyncio.shield(aw)

Bảo vệ awaitable object khỏi bị cancelled.

Nếu aw là một coroutine thì nó sẽ tự động được lên lịch dưới dạng Tác vụ.

Tuyên bố:

nhiệm vụ = asyncio.create_task(something())
res =  chắn chờ đợi (nhiệm vụ)

tương đương với:

res = đang chờ đợi điều  đó()

except rằng nếu coroutine chứa nó bị hủy thì Tác vụ đang chạy trong something() cũng không bị hủy. Theo quan điểm của something(), việc hủy bỏ đã không xảy ra. Mặc dù người gọi nó vẫn bị hủy, nhưng biểu thức "chờ" vẫn tăng CancelledError.

Nếu something() bị hủy bằng cách khác (tức là từ bên trong chính nó) thì điều đó cũng sẽ hủy shield().

Nếu muốn bỏ qua hoàn toàn việc hủy (không được khuyến nghị), hàm shield() phải được kết hợp với mệnh đề thử/ngoại trừ, như sau:

nhiệm vụ = asyncio.create_task(something())
thử:
    res =  chắn chờ đợi (nhiệm vụ)
ngoại trừ Đã hủyError:
    res = Không 

Quan trọng

Lưu tham chiếu đến các tác vụ được chuyển đến hàm này để tránh tác vụ biến mất trong quá trình thực thi. Vòng lặp sự kiện chỉ giữ các tham chiếu yếu đến các tác vụ. Một tác vụ không được tham chiếu ở nơi khác có thể được thu gom rác bất cứ lúc nào, ngay cả trước khi nó được thực hiện.

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Sắp loại bỏ từ phiên bản 3.10: Cảnh báo không dùng nữa được đưa ra nếu aw không phải là đối tượng giống Tương lai và không có vòng lặp sự kiện đang chạy.

Hết giờ

asyncio.timeout(delay)

Trả về asynchronous context manager có thể được sử dụng để giới hạn lượng thời gian chờ đợi một thứ gì đó.

delay có thể là None hoặc số float/int số giây để chờ. Nếu delayNone thì sẽ không áp dụng giới hạn thời gian; điều này có thể hữu ích nếu không xác định được độ trễ khi trình quản lý bối cảnh được tạo.

Trong cả hai trường hợp, trình quản lý bối cảnh có thể được lên lịch lại sau khi tạo bằng Timeout.reschedule().

Ví dụ:

async def main():
    không đồng bộ với asyncio.timeout(10):
        đang chờ long_running_task()

Nếu long_running_task mất hơn 10 giây để hoàn thành, trình quản lý bối cảnh sẽ hủy tác vụ hiện tại và xử lý asyncio.CancelledError kết quả trong nội bộ, chuyển nó thành TimeoutError có thể bị bắt và xử lý.

Ghi chú

Trình quản lý bối cảnh asyncio.timeout() là thứ biến asyncio.CancelledError thành TimeoutError, có nghĩa là TimeoutError chỉ có thể bắt được outside của trình quản lý bối cảnh.

Ví dụ về việc bắt TimeoutError:

async def main():
    thử:
        không đồng bộ với asyncio.timeout(10):
            đang chờ long_running_task()
    ngoại trừ Hết thời gianLỗi:
        print("Thao tác kéo dài đã hết thời gian chờ, nhưng chúng tôi đã xử lý được.")

    print("Câu lệnh này sẽ vẫn chạy bất kể.")

Trình quản lý bối cảnh do asyncio.timeout() tạo ra có thể được lên lịch lại cho một thời hạn khác và được kiểm tra.

class asyncio.Timeout(when)

Một asynchronous context manager để hủy các coroutine quá hạn.

Thích sử dụng asyncio.timeout() hoặc asyncio.timeout_at() hơn là khởi tạo trực tiếp Timeout.

when phải là thời điểm tuyệt đối mà ngữ cảnh sẽ hết thời gian, được đo bằng đồng hồ của vòng lặp sự kiện:

  • Nếu whenNone, thời gian chờ sẽ không bao giờ được kích hoạt.

  • Nếu when < loop.time(), thời gian chờ sẽ kích hoạt ở lần lặp tiếp theo của vòng lặp sự kiện.

when() float | None

Trả về thời hạn hiện tại hoặc None nếu thời hạn hiện tại chưa được đặt.

reschedule(when: float | None)

Lên lịch lại thời gian chờ.

expired() bool

Trả về xem trình quản lý bối cảnh đã vượt quá thời hạn (hết hạn) hay chưa.

Ví dụ:

async def main():
    thử:
        # We không biết thời gian chờ khi bắt đầu nên chúng tôi chuyển ``None``.
        không đồng bộ với asyncio.timeout(None) dưới dạng cm:
            # We biết thời gian chờ bây giờ nên chúng tôi lên lịch lại.
            new_deadline = get_running_loop().time() + 10
            cm.reschedule(new_deadline)

            đang chờ long_running_task()
    ngoại trừ Hết thời gianLỗi:
        vượt qua

    nếu cm.expired():
        print("Có vẻ như chúng ta chưa hoàn thành đúng thời hạn.")

Trình quản lý bối cảnh hết thời gian chờ có thể được lồng vào nhau một cách an toàn.

Added in version 3.11.

asyncio.timeout_at(when)

Tương tự như asyncio.timeout(), ngoại trừ when là thời điểm tuyệt đối để ngừng chờ đợi, hay None.

Ví dụ:

async def main():
    vòng lặp = get_running_loop()
    thời hạn = loop.time() + 20
    thử:
        không đồng bộ với asyncio.timeout_at(hạn chót):
            đang chờ long_running_task()
    ngoại trừ Hết thời gianLỗi:
        print("Thao tác kéo dài đã hết thời gian chờ, nhưng chúng tôi đã xử lý được.")

    print("Câu lệnh này sẽ vẫn chạy bất kể.")

Added in version 3.11.

async asyncio.wait_for(aw, timeout)

Đợi aw awaitable hoàn thành với thời gian chờ.

Nếu aw là một coroutine thì nó sẽ tự động được lên lịch dưới dạng Tác vụ.

timeout có thể là None hoặc float hoặc int số giây để chờ. Nếu timeoutNone, hãy chặn cho đến khi tương lai hoàn thành.

Nếu hết thời gian chờ, nó sẽ hủy tác vụ và tăng TimeoutError.

Để tránh nhiệm vụ cancellation, hãy bọc nó trong shield().

Hàm này sẽ đợi cho đến khi tương lai thực sự bị hủy, do đó tổng thời gian chờ có thể vượt quá timeout. Nếu một ngoại lệ xảy ra trong quá trình hủy, nó sẽ được truyền đi.

Nếu quá trình chờ bị hủy, aw trong tương lai cũng bị hủy.

Ví dụ:

async def vĩnh cửu():
    # Sleep trong một giờ
    đang chờ asyncio.sleep(3600)
    in('yay!')

async def main():
    # Wait trong tối đa 1 giây
    thử:
        đang chờ asyncio.wait_for(eternity(), timeout=1.0)
    ngoại trừ Hết thời gianLỗi:
        in('hết giờ!')

asyncio.run(chính())

đầu ra # Expected:
#
#     timeout!

Thay đổi trong phiên bản 3.7: Khi aw bị hủy do hết thời gian chờ, wait_for sẽ đợi aw bị hủy. Lúc trước nó kêu TimeoutError ngay lập tức.

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Thay đổi trong phiên bản 3.11: Tăng TimeoutError thay vì asyncio.TimeoutError.

Đang chờ nguyên thủy

async asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)

Chạy đồng thời các phiên bản FutureTask trong aws có thể lặp lại và chặn cho đến khi điều kiện được chỉ định bởi return_when.

Lặp lại aws không được để trống.

Trả về hai bộ Nhiệm vụ/Tương lai: (done, pending).

Cách sử dụng:

xong, đang chờ xử  = đang chờ asyncio.wait(aws)

timeout (một float hoặc int), nếu được chỉ định, có thể được sử dụng để kiểm soát số giây tối đa phải chờ trước khi quay lại.

Lưu ý rằng chức năng này không tăng TimeoutError. Tương lai hoặc Nhiệm vụ không được thực hiện khi hết thời gian chờ sẽ được trả về trong tập thứ hai.

return_when cho biết khi nào hàm này sẽ quay trở lại. Nó phải là một trong các hằng số sau:

Hằng số

Mô tả

asyncio.FIRST_COMPLETED

Hàm sẽ quay trở lại khi bất kỳ thao tác nào trong tương lai kết thúc hoặc bị hủy.

asyncio.FIRST_EXCEPTION

Hàm sẽ trả về khi bất kỳ tương lai nào kết thúc bằng cách đưa ra một ngoại lệ. Nếu không có tương lai nào đưa ra ngoại lệ thì nó tương đương với ALL_COMPLETED.

asyncio.ALL_COMPLETED

Hàm sẽ trả về khi tất cả hợp đồng tương lai kết thúc hoặc bị hủy.

Không giống như wait_for(), wait() không hủy hợp đồng tương lai khi hết thời gian chờ.

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Thay đổi trong phiên bản 3.11: Việc truyền trực tiếp các đối tượng coroutine tới wait() đều bị cấm.

Thay đổi trong phiên bản 3.12: Đã thêm hỗ trợ cho các nhiệm vụ tạo ra năng suất.

asyncio.as_completed(aws, *, timeout=None)

Chạy đồng thời awaitable objects trong aws iterable. Đối tượng được trả về có thể được lặp lại để thu được kết quả của các đối tượng có thể chờ đợi khi chúng hoàn thành.

Đối tượng được trả về bởi as_completed() có thể được lặp lại dưới dạng asynchronous iterator hoặc iterator đơn giản. Khi sử dụng phép lặp không đồng bộ, các sản phẩm có thể chờ được cung cấp ban đầu sẽ được cung cấp nếu chúng là nhiệm vụ hoặc tương lai. Điều này giúp dễ dàng liên hệ các nhiệm vụ đã lên lịch trước đó với kết quả của chúng. Ví dụ:

ipv4_connect = create_task(open_connection("127.0.0.1", 80))
ipv6_connect = create_task(open_connection("::1", 80))
nhiệm vụ = [ipv4_connect, ipv6_connect]

không đồng bộ cho kết nối sớm nhất trong as_completed(task):
    # earliest_connect đã xong. Kết quả có thể thu được bằng cách
    # awaiting hoặc gọi sớm nhất_connect.result()
    người đọc, người viết = chờ đợi sớm nhất_kết nối

    nếu sớm nhất_connect  ipv6_connect:
        print("Đã thiết lập kết nối IPv6.")
    khác:
        print("Đã thiết lập kết nối IPv4.")

Trong quá trình lặp không đồng bộ, các tác vụ được tạo ngầm sẽ được cung cấp cho các sản phẩm chờ được cung cấp không phải là nhiệm vụ hoặc tương lai.

Khi được sử dụng như một trình lặp đơn giản, mỗi lần lặp sẽ tạo ra một coroutine mới trả về kết quả hoặc đưa ra ngoại lệ của đối tượng có thể chờ hoàn thành tiếp theo. Mẫu này tương thích với các phiên bản Python cũ hơn 3.13:

ipv4_connect = create_task(open_connection("127.0.0.1", 80))
ipv6_connect = create_task(open_connection("::1", 80))
nhiệm vụ = [ipv4_connect, ipv6_connect]

cho next_connect trong as_completed(task):
    # next_connect không phải là một trong những đối tượng tác vụ ban đầu. Nó phải như vậy
    # awaited để lấy giá trị kết quả hoặc đưa ra ngoại lệ của
    # awaitable sẽ kết thúc tiếp theo.
    người đọc, người viết = đang chờ next_connect

Một TimeoutError được nâng lên nếu hết thời gian chờ trước khi tất cả các mục có thể chờ được hoàn thành. Điều này được tạo ra bởi vòng lặp async for trong quá trình lặp không đồng bộ hoặc bởi các coroutine được tạo ra trong quá trình lặp đơn giản.

Thay đổi trong phiên bản 3.10: Đã xóa tham số loop.

Sắp loại bỏ từ phiên bản 3.10: Cảnh báo không dùng nữa được đưa ra nếu không phải tất cả các đối tượng có thể chờ đợi trong vòng lặp aws đều là các đối tượng giống Tương lai và không có vòng lặp sự kiện đang chạy.

Thay đổi trong phiên bản 3.12: Đã thêm hỗ trợ cho các nhiệm vụ tạo ra năng suất.

Thay đổi trong phiên bản 3.13: Kết quả hiện có thể được sử dụng dưới dạng asynchronous iterator hoặc iterator đơn giản (trước đây nó chỉ là một trình vòng lặp đơn giản).

Chạy trong chủ đề

async asyncio.to_thread(func, /, *args, **kwargs)

Chức năng chạy không đồng bộ func trong một luồng riêng biệt.

Bất kỳ *args and **kwargs supplied for this function are directly passed to func. Ngoài ra, contextvars.Context hiện tại được truyền bá, cho phép truy cập các biến ngữ cảnh từ chuỗi vòng lặp sự kiện trong chuỗi riêng biệt.

Trả về một coroutine có thể chờ để nhận được kết quả cuối cùng là func.

Hàm coroutine này chủ yếu nhằm mục đích sử dụng để thực thi các hàm/phương thức liên kết IO mà lẽ ra sẽ chặn vòng lặp sự kiện nếu chúng được chạy trong luồng chính. Ví dụ:

chặn chắc chắn_io():
    print(f"bắt đầu chặn_io lúc {time.strftime('%X')}")
    # Note rằng time.sleep() có thể được thay thế bằng bất kỳ lệnh chặn nào
    hoạt động # IO-bound, chẳng hạn như hoạt động tập tin.
    thời gian.ngủ(1)
    print(f"blocking_io hoàn thành lúc {time.strftime('%X')}")

async def main():
    print(f"bắt đầu chính vào lúc {time.strftime('%X')}")

    đang chờ asyncio.gather(
        asyncio.to_thread(blocking_io),
        asyncio.sleep(1))

    print(f"đã hoàn thành phần chính lúc {time.strftime('%X')}")


asyncio.run(chính())

đầu ra # Expected:
#
# started chính lúc 19:50:53
# start chặn_io lúc 19:50:53
# blocking_io hoàn thành lúc 19:50:54
# finished chính lúc 19:50:54

Việc gọi trực tiếp blocking_io() trong bất kỳ coroutine nào sẽ chặn vòng lặp sự kiện trong suốt thời gian của nó, khiến thời gian chạy tăng thêm 1 giây. Thay vào đó, bằng cách sử dụng asyncio.to_thread(), chúng ta có thể chạy nó trong một luồng riêng biệt mà không chặn vòng lặp sự kiện.

Ghi chú

Do GIL, asyncio.to_thread() thường chỉ có thể được sử dụng để làm cho các hàm liên kết IO không bị chặn. Tuy nhiên, đối với các mô-đun mở rộng phát hành GIL hoặc các triển khai Python thay thế không có, asyncio.to_thread() cũng có thể được sử dụng cho các hàm gắn với CPU.

Added in version 3.9.

Lập lịch từ các chủ đề khác

asyncio.run_coroutine_threadsafe(coro, loop)

Gửi một coroutine đến vòng lặp sự kiện nhất định. Chủ đề an toàn.

Trả về concurrent.futures.Future để chờ kết quả từ một chuỗi hệ điều hành khác.

Hàm này được gọi từ một luồng hệ điều hành khác với luồng mà vòng lặp sự kiện đang chạy. Ví dụ:

def in_thread(loop: asyncio.AbstractEventLoop) -> Không :
    # Run chặn IO
    pathlib.Path("example.txt").write_text("xin chào thế giới",  hóa="utf8")

    # Create một coroutine
    coro = asyncio.sleep(1, result=3)

    # Submit coroutine vào một vòng lặp nhất định
    tương lai = asyncio.run_coroutine_threadsafe(coro, loop)

    # Wait để biết kết quả với đối số hết thời gian tùy chọn
    khẳng định tương lai.result(timeout=2) == 3

async def amain() -> Không :
    # Get vòng lặp đang chạy
    vòng lặp = asyncio.get_running_loop()

    # Run có gì đó trong một chủ đề
    đang chờ asyncio.to_thread(in_thread, loop)

Cũng có thể chạy theo cách khác. Ví dụ:

@contextlib.contextmanager
def loop_in_thread() -> Trình tạo [asyncio.AbstractEventLoop]:
    loop_fut = concurrent.futures.Future[asyncio.AbstractEventLoop]()
    stop_event = asyncio.Event()

    async def main() -> Không :
        loop_fut.set_result(asyncio.get_running_loop())
        đang chờ stop_event.wait()

    với concurrent.futures.ThreadPoolExecutor(1)  tpe:
        Complete_fut = tpe.submit(asyncio.run, main())
        cho fut trong concurrent.futures.as_completed((loop_fut, Complete_fut)):
            nếu tương lai  loop_fut:
                vòng lặp = loop_fut.result()
                thử:
                    vòng lặp năng suất
                cuối cùng:
                    loop.call_soon_threadsafe(stop_event.set)
            khác:
                fut.result()

# Create một vòng lặp trong một chủ đề khác
với loop_in_thread()  vòng lặp:
    # Create một coroutine
    coro = asyncio.sleep(1, result=3)

    # Submit coroutine vào một vòng lặp nhất định
    tương lai = asyncio.run_coroutine_threadsafe(coro, loop)

    # Wait để biết kết quả với đối số hết thời gian tùy chọn
    khẳng định tương lai.result(timeout=2) == 3

Nếu một ngoại lệ được nêu ra trong coroutine thì Tương lai được trả về sẽ được thông báo. Nó cũng có thể được sử dụng để hủy tác vụ trong vòng lặp sự kiện:

thử:
    kết quả = tương lai.result (hết thời gian)
ngoại trừ Hết thời gianLỗi:
    print('Coroutine mất quá nhiều thời gian, hủy tác vụ...')
    tương lai.cancel()
ngoại trừ Ngoại lệ như exec:
    print(f'Coroutine đưa ra một ngoại lệ: {exc!r}')
khác:
    print(f'Coroutine trả về: {result!r}')

Xem phần concurrency and multithreading của tài liệu.

Không giống như các hàm asyncio khác, hàm này yêu cầu đối số loop phải được truyền một cách rõ ràng.

Added in version 3.5.1.

Xem xét nội tâm

asyncio.current_task(loop=None)

Trả về phiên bản Task hiện đang chạy hoặc None nếu không có tác vụ nào đang chạy.

Nếu loopNone get_running_loop() được sử dụng để lấy vòng lặp hiện tại.

Added in version 3.7.

asyncio.all_tasks(loop=None)

Trả về một tập hợp các đối tượng Task chưa hoàn thành do vòng lặp chạy.

Nếu loopNone, get_running_loop() được sử dụng để lấy vòng lặp hiện tại.

Added in version 3.7.

asyncio.iscoroutine(obj)

Trả về True nếu obj là đối tượng coroutine.

Added in version 3.4.

Đối tượng nhiệm vụ

class asyncio.Task(coro, *, loop=None, name=None, context=None, eager_start=False)

Một đối tượng Future-like chạy Python coroutine. Không an toàn chủ đề.

Tác vụ được dùng để chạy coroutine trong vòng lặp sự kiện. Nếu một coroutine đang chờ trong Tương lai, Tác vụ sẽ tạm dừng việc thực thi coroutine và chờ cho đến khi Tương lai hoàn thành. Khi Tương lai là done, quá trình thực thi coroutine được bao bọc sẽ tiếp tục.

Vòng lặp sự kiện sử dụng lập lịch hợp tác: vòng lặp sự kiện chạy một Nhiệm vụ tại một thời điểm. Trong khi Nhiệm vụ chờ hoàn thành Tương lai, vòng lặp sự kiện sẽ chạy các Nhiệm vụ khác, lệnh gọi lại hoặc thực hiện các thao tác IO.

Sử dụng hàm asyncio.create_task() cấp cao để tạo Nhiệm vụ hoặc các hàm loop.create_task() hoặc ensure_future() cấp thấp. Việc khởi tạo Nhiệm vụ theo cách thủ công không được khuyến khích.

Để hủy một Tác vụ đang chạy, hãy sử dụng phương thức cancel(). Việc gọi nó sẽ khiến Tác vụ ném ngoại lệ CancelledError vào coroutine được bao bọc. Nếu một coroutine đang chờ trên một đối tượng Future trong quá trình hủy, đối tượng Future sẽ bị hủy.

cancelled() có thể được sử dụng để kiểm tra xem Tác vụ có bị hủy hay không. Phương thức này trả về True nếu coroutine được bao bọc không loại bỏ ngoại lệ CancelledError và thực sự đã bị hủy.

asyncio.Task kế thừa từ Future tất cả các API của nó ngoại trừ Future.set_result()Future.set_exception().

Đối số context chỉ có từ khóa tùy chọn cho phép chỉ định một contextvars.Context tùy chỉnh để coro chạy vào. Nếu không cung cấp context, Tác vụ sẽ sao chép ngữ cảnh hiện tại và sau đó chạy coroutine của nó trong ngữ cảnh được sao chép.

Đối số eager_start chỉ có từ khóa tùy chọn cho phép bắt đầu háo hức thực thi asyncio.Task tại thời điểm tạo tác vụ. Nếu được đặt thành True và vòng lặp sự kiện đang chạy, tác vụ sẽ bắt đầu thực thi coroutine ngay lập tức, cho đến khi coroutine chặn lần đầu tiên. Nếu coroutine quay trở lại hoặc tăng lên mà không bị chặn, nhiệm vụ sẽ được hoàn thành một cách háo hức và sẽ bỏ qua việc lên lịch cho vòng lặp sự kiện.

Thay đổi trong phiên bản 3.7: Đã thêm hỗ trợ cho mô-đun contextvars.

Thay đổi trong phiên bản 3.8: Đã thêm tham số name.

Sắp loại bỏ từ phiên bản 3.10: Cảnh báo không dùng nữa được phát ra nếu loop không được chỉ định và không có vòng lặp sự kiện đang chạy.

Thay đổi trong phiên bản 3.11: Đã thêm tham số context.

Thay đổi trong phiên bản 3.12: Đã thêm tham số eager_start.

done()

Trả về True nếu Nhiệm vụ là done.

Nhiệm vụ là done khi coroutine được bao bọc trả về một giá trị, đưa ra ngoại lệ hoặc Nhiệm vụ bị hủy.

result()

Trả về kết quả của Task.

Nếu Tác vụ là done thì kết quả của coroutine được bao bọc sẽ được trả về (hoặc nếu coroutine đưa ra một ngoại lệ thì ngoại lệ đó sẽ được đưa ra lại.)

Nếu Tác vụ là cancelled, phương pháp này sẽ đưa ra một ngoại lệ CancelledError.

Nếu kết quả của Nhiệm vụ chưa có, phương pháp này sẽ đưa ra ngoại lệ InvalidStateError.

exception()

Trả về ngoại lệ của Nhiệm vụ.

Nếu coroutine được bao bọc đưa ra một ngoại lệ thì ngoại lệ đó sẽ được trả về. Nếu coroutine được gói trả về bình thường thì phương thức này trả về None.

Nếu Tác vụ là cancelled, phương pháp này sẽ đưa ra một ngoại lệ CancelledError.

Nếu Tác vụ chưa phải là done thì phương pháp này sẽ đưa ra một ngoại lệ InvalidStateError.

add_done_callback(callback, *, context=None)

Thêm lệnh gọi lại để chạy khi Tác vụ là done.

Phương pháp này chỉ nên được sử dụng trong mã dựa trên lệnh gọi lại cấp thấp.

Xem tài liệu của Future.add_done_callback() để biết thêm chi tiết.

remove_done_callback(callback)

Xóa callback khỏi danh sách gọi lại.

Phương pháp này chỉ nên được sử dụng trong mã dựa trên lệnh gọi lại cấp thấp.

Xem tài liệu của Future.remove_done_callback() để biết thêm chi tiết.

get_stack(*, limit=None)

Trả về danh sách các khung ngăn xếp cho Tác vụ này.

Nếu coroutine được bao bọc không được thực hiện, thao tác này sẽ trả về ngăn xếp nơi nó bị treo. Nếu coroutine đã hoàn thành thành công hoặc bị hủy, kết quả này sẽ trả về một danh sách trống. Nếu coroutine bị chấm dứt bởi một ngoại lệ, thì kết quả này sẽ trả về danh sách các khung truy nguyên.

Các khung hình luôn được sắp xếp từ cũ nhất đến mới nhất.

Chỉ một khung ngăn xếp được trả về cho một coroutine bị treo.

Đối số limit tùy chọn đặt số lượng khung hình tối đa cần trả về; theo mặc định tất cả các khung có sẵn sẽ được trả về. Thứ tự của danh sách được trả về khác nhau tùy thuộc vào việc trả về một ngăn xếp hay truy ngược: các khung mới nhất của ngăn xếp được trả về, nhưng các khung cũ nhất của truy nguyên được trả về. (Điều này phù hợp với hành vi của mô-đun truy nguyên.)

print_stack(*, limit=None, file=None)

In ngăn xếp hoặc truy nguyên cho Nhiệm vụ này.

Điều này tạo ra đầu ra tương tự như đầu ra của mô-đun truy nguyên cho các khung được get_stack() truy xuất.

Đối số limit được truyền trực tiếp tới get_stack().

Đối số file là luồng I/O mà đầu ra được ghi vào đó; theo mặc định, đầu ra được ghi vào sys.stdout.

get_coro()

Trả về đối tượng coroutine được bao bọc bởi Task.

Ghi chú

Điều này sẽ trả về None cho các Nhiệm vụ đã hoàn thành một cách háo hức. Xem Eager Task Factory.

Added in version 3.8.

Thay đổi trong phiên bản 3.12: Việc thực thi tác vụ háo hức mới được thêm vào có nghĩa là kết quả có thể là None.

get_context()

Trả về đối tượng contextvars.Context được liên kết với tác vụ.

Added in version 3.12.

get_name()

Trả về tên của Nhiệm vụ.

Nếu không có tên nào được gán rõ ràng cho Tác vụ thì việc triển khai Tác vụ asyncio mặc định sẽ tạo ra một tên mặc định trong quá trình khởi tạo.

Added in version 3.8.

set_name(value)

Đặt tên của Nhiệm vụ.

Đối số value có thể là bất kỳ đối tượng nào, sau đó được chuyển đổi thành một chuỗi.

Trong quá trình triển khai Tác vụ mặc định, tên sẽ hiển thị trong đầu ra repr() của đối tượng tác vụ.

Added in version 3.8.

cancel(msg=None)

Yêu cầu hủy bỏ nhiệm vụ.

Nếu Tác vụ đã có done hoặc cancelled, hãy trả về False, nếu không, hãy trả về True.

Phương thức này sắp xếp để đưa một ngoại lệ CancelledError vào coroutine được bao bọc trong chu kỳ tiếp theo của vòng lặp sự kiện.

Sau đó, coroutine có cơ hội dọn dẹp hoặc thậm chí từ chối yêu cầu bằng cách loại bỏ ngoại lệ bằng khối try ... ... except CancelledError ... finally. Do đó, không giống như Future.cancel(), Task.cancel() không đảm bảo rằng Nhiệm vụ sẽ bị hủy, mặc dù việc ngăn chặn hoàn toàn việc hủy không phổ biến và thường không được khuyến khích. Tuy nhiên, nếu coroutine quyết định ngăn chặn việc hủy, nó sẽ phải gọi Task.uncancel() ngoài việc bắt ngoại lệ.

Thay đổi trong phiên bản 3.9: Đã thêm tham số msg.

Thay đổi trong phiên bản 3.11: Tham số msg được truyền từ tác vụ bị hủy đến bộ chờ của nó.

Ví dụ sau minh họa cách coroutine có thể chặn yêu cầu hủy:

async def cancel_me():
    print('cancel_me(): trước khi ngủ')

    thử:
        # Wait trong 1 giờ
        đang chờ asyncio.sleep(3600)
    ngoại trừ asyncio.CancelledError:
        print('cancel_me(): hủy chế độ ngủ')
        nâng cao
    cuối cùng:
        print('cancel_me(): sau khi ngủ')

async def main():
    # Create nhiệm vụ "hủy_me"
    nhiệm vụ = asyncio.create_task(cancel_me())

    # Wait trong 1 giây
    đang chờ asyncio.sleep(1)

    nhiệm vụ.cancel()
    thử:
        chờ đợi nhiệm vụ
    ngoại trừ asyncio.CancelledError:
        print("main(): cancel_me hiện đã bị hủy")

asyncio.run(chính())

đầu ra # Expected:
#
#     cancel_me(): trước khi ngủ
#     cancel_me(): hủy chế độ ngủ
#     cancel_me(): sau khi ngủ
#     main(): cancel_me hiện đã bị hủy
cancelled()

Trả về True nếu Nhiệm vụ là cancelled.

Nhiệm vụ là cancelled khi yêu cầu hủy với cancel() và coroutine được bao bọc đã truyền bá ngoại lệ CancelledError được ném vào đó.

uncancel()

Giảm số lượng yêu cầu hủy đối với Nhiệm vụ này.

Trả về số lượng yêu cầu hủy còn lại.

Lưu ý rằng sau khi hoàn thành việc thực thi tác vụ bị hủy, các lệnh gọi tiếp theo tới uncancel() sẽ không có hiệu lực.

Added in version 3.11.

Phương pháp này được sử dụng bởi nội bộ của asyncio và dự kiến sẽ không được sử dụng bởi mã người dùng cuối. Đặc biệt, nếu một Tác vụ được hủy hủy thành công, điều này cho phép các thành phần đồng thời có cấu trúc như Nhóm nhiệm vụasyncio.timeout() tiếp tục chạy, cách ly tính năng hủy đối với khối có cấu trúc tương ứng. Ví dụ:

async def make_request_with_timeout():
    thử:
        không đồng bộ với asyncio.timeout(1):
            Khối # Structured bị ảnh hưởng bởi thời gian chờ:
            đang chờ make_request()
            đang chờ make_another_request()
    ngoại trừ Hết thời gianLỗi:
        log("Đã hết thời gian chờ")
     # Outer không bị ảnh hưởng bởi thời gian chờ:
    đang chờ không liên quan_code()

Mặc dù khối có make_request()make_another_request() có thể bị hủy do hết thời gian chờ, nhưng unrelated_code() sẽ tiếp tục chạy ngay cả trong trường hợp hết thời gian chờ. Điều này được thực hiện với uncancel(). Trình quản lý bối cảnh TaskGroup sử dụng uncancel() theo cách tương tự.

Nếu vì lý do nào đó, mã người dùng cuối ngăn chặn việc hủy bằng cách bắt CancelledError, thì mã đó cần gọi phương thức này để xóa trạng thái hủy.

Khi phương thức này giảm số lần hủy xuống 0, phương thức này sẽ kiểm tra xem lệnh gọi cancel() trước đó có sắp xếp để đưa CancelledError vào tác vụ hay không. Nếu nó chưa được ném ra, sự sắp xếp đó sẽ bị hủy bỏ (bằng cách đặt lại cờ _must_cancel bên trong).

Thay đổi trong phiên bản 3.13: Đã thay đổi để hủy bỏ các yêu cầu hủy đang chờ xử lý khi đạt đến số 0.

cancelling()

Trả về số lượng yêu cầu hủy đang chờ xử lý cho Tác vụ này, tức là số lượng cuộc gọi đến cancel() ít hơn số lượng cuộc gọi uncancel().

Lưu ý rằng nếu số này lớn hơn 0 nhưng Task vẫn đang thực thi thì cancelled() vẫn sẽ trả về False. Điều này là do con số này có thể được hạ xuống bằng cách gọi uncancel(), điều này có thể dẫn đến việc nhiệm vụ không bị hủy nếu yêu cầu hủy giảm xuống 0.

Phương pháp này được sử dụng bởi nội bộ của asyncio và dự kiến sẽ không được sử dụng bởi mã người dùng cuối. Xem uncancel() để biết thêm chi tiết.

Added in version 3.11.