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 gì) 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 asyncioTasks.Hãy sửa đổi ví dụ trên và chạy hai coroutine
say_afterconcurrently: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.TaskGroupcung cấp một giải pháp thay thế hiện đại hơn chocreate_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, Tasks và Futures.
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
Taskvà 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.Contexttù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.TaskGroup và asyncio.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ẽ đóngcorođã 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 KeyboardInterrupt và SystemExit 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
ValueErrornếu delay lànan.
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_exceptions là
False(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êngather(). 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_exceptions là
True, 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()là 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 aws là cancelled, thì nhiệm vụ đó sẽ được xử lý như thể nó đã tăng
CancelledError-- lệnh gọigather()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ựngTask. 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ìTaskmặ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ớiasyncio.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 = lá chắn chờ đợi (nhiệm vụ)
tương đương với:
res = đang chờ đợi điều gì đó()
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ủasomething(), 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ăngCancelledError.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ủyshield().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 = lá chắn chờ đợi (nhiệm vụ) ngoại trừ Đã hủyError: res = Không có
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à
Nonehoặc số float/int số giây để chờ. Nếu delay làNonethì 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_taskmấ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.CancelledErrorkết quả trong nội bộ, chuyển nó thànhTimeoutErrorcó thể bị bắt và xử lý.Ghi chú
Trình quản lý bối cảnh
asyncio.timeout()là thứ biếnasyncio.CancelledErrorthànhTimeoutError, có nghĩa làTimeoutErrorchỉ 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ặcasyncio.timeout_at()hơn là khởi tạo trực tiếpTimeout.whenphả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
whenlàNone, 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.
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, hayNone.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à
Nonehoặc float hoặc int số giây để chờ. Nếu timeout làNone, 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ó trongshield().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_forsẽ đợi aw bị hủy. Lúc trước nó kêuTimeoutErrorngay 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
TimeoutErrorthay 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
FuturevàTasktrong 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ử lý = đ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 là 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ặpasync fortrong 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.Contexthiệ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ụngasyncio.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 có: # Run chặn IO pathlib.Path("example.txt").write_text("xin chào thế giới", mã 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 có: # 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 có: loop_fut.set_result(asyncio.get_running_loop()) đang chờ stop_event.wait() với concurrent.futures.ThreadPoolExecutor(1) là tpe: Complete_fut = tpe.submit(asyncio.run, main()) cho fut trong concurrent.futures.as_completed((loop_fut, Complete_fut)): nếu tương lai là 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() là 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
Taskhiện đang chạy hoặcNonenếu không có tác vụ nào đang chạy.Nếu loop là
Noneget_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
Taskchưa hoàn thành do vòng lặp chạy.Nếu loop là
None,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ề
Truenế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-likechạ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àmloop.create_task()hoặcensure_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ệCancelledErrorvà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ềTruenếu coroutine được bao bọc không loại bỏ ngoại lệCancelledErrorvà thực sự đã bị hủy.asyncio.Taskkế thừa từFuturetất cả các API của nó ngoại trừFuture.set_result()vàFuture.set_exception().Đối số context chỉ có từ khóa tùy chọn cho phép chỉ định một
contextvars.Contexttù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.Tasktại thời điểm tạo tác vụ. Nếu được đặt thànhTruevà 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ề
Truenế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ề
Nonecho 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ệ
CancelledErrorvà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ọiTask.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ề
Truenế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ụ 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ờ") Mã # 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()vàmake_another_request()có thể bị hủy do hết thời gian chờ, nhưngunrelated_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ớiuncancel(). Trình quản lý bối cảnhTaskGroupsử dụnguncancel()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 để đưaCancelledErrorvà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_cancelbê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ọiuncancel().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ọiuncancel(), đ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.