Thông tin thực tế:
Bắt đầu từ Python 3.7, asyncio.create_task(coro)
hàm cấp cao đã được thêm vào cho mục đích này.
Bạn nên sử dụng nó thay vì các cách khác để tạo nhiệm vụ từ thời gian đăng quang. Tuy nhiên, nếu bạn cần tạo tác vụ từ chờ tùy ý, bạn nên sử dụng asyncio.ensure_future(obj)
.
Thông tin cũ:
ensure_future
vs create_task
ensure_future
là một phương pháp để tạo Task
từ coroutine
. Nó tạo ra các tác vụ theo những cách khác nhau dựa trên đối số (bao gồm cả việc sử dụng create_task
for coroutines và các đối tượng tương lai).
create_task
là một phương pháp trừu tượng của AbstractEventLoop
. Các vòng lặp sự kiện khác nhau có thể triển khai chức năng này theo những cách khác nhau.
Bạn nên sử dụng ensure_future
để tạo nhiệm vụ. Bạn create_task
chỉ cần thực hiện loại vòng lặp sự kiện của riêng mình.
Cập nhật:
@ bj0 đã chỉ vào câu trả lời của Guido về chủ đề này:
Vấn đề ensure_future()
là nếu bạn có một cái gì đó có thể là một quy trình đăng quang hoặc một Future
(cái sau bao gồm một Task
vì đó là một lớp con của Future
) và bạn muốn có thể gọi một phương thức trên đó chỉ được xác định trên Future
(có thể là về ví dụ hữu ích đang cancel()
). Khi nó đã là một Future
(hoặc Task
) điều này không làm gì cả; khi nó là một quy trình, nó sẽ bao bọc nó trong một Task
.
Nếu bạn biết rằng bạn có một quy trình đăng ký và bạn muốn nó được lên lịch, thì API chính xác để sử dụng là create_task()
. Thời điểm duy nhất khi bạn nên gọi ensure_future()
là khi bạn đang cung cấp một API (giống như hầu hết các API riêng của asyncio) chấp nhận một quy trình đăng ký hoặc một quy trình đăng ký Future
và bạn cần phải làm gì đó với nó mà yêu cầu bạn phải có Future
.
và sau đó:
Cuối cùng, tôi vẫn tin rằng đó ensure_future()
là một cái tên ít người biết đến cho một phần chức năng hiếm khi cần thiết. Khi tạo một nhiệm vụ từ một quy trình đăng ký, bạn nên sử dụng tên thích hợp
loop.create_task()
. Có lẽ nên có một bí danh cho điều đó
asyncio.create_task()
?
Thật là ngạc nhiên đối với tôi. Động lực chính của tôi khi sử dụng ensure_future
tất cả là chức năng cấp cao hơn của nó so với thành viên của vòng lặp create_task
(thảo luận chứa một số ý tưởng như thêm asyncio.spawn
hoặc asyncio.create_task
).
Tôi cũng có thể chỉ ra rằng theo ý kiến của tôi, khá tiện lợi khi sử dụng hàm phổ quát có thể xử lý bất kỳ Awaitable
thay vì chỉ coroutines.
Tuy nhiên, câu trả lời của Guido rất rõ ràng: "Khi tạo một nhiệm vụ từ một chương trình điều tra, bạn nên sử dụng tên phù hợp loop.create_task()
"
Khi nào coroutines nên được gói trong các nhiệm vụ?
Kết thúc quy trình đăng ký trong một Nhiệm vụ - là một cách để bắt đầu quy trình đăng ký này "trong nền". Đây là ví dụ:
import asyncio
async def msg(text):
await asyncio.sleep(0.1)
print(text)
async def long_operation():
print('long_operation started')
await asyncio.sleep(3)
print('long_operation finished')
async def main():
await msg('first')
# Now you want to start long_operation, but you don't want to wait it finised:
# long_operation should be started, but second msg should be printed immediately.
# Create task to do so:
task = asyncio.ensure_future(long_operation())
await msg('second')
# Now, when you want, you can await task finised:
await task
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Đầu ra:
first
long_operation started
second
long_operation finished
Bạn có thể thay thế asyncio.ensure_future(long_operation())
bằng chỉ await long_operation()
để cảm nhận sự khác biệt.
create_task
nếu bạn thực sự cần aa đối tượng nhiệm vụ, mà bạn thường không cần: github.com/python/asyncio/issues/477#issuecomment-268709555