Terkadang ada beberapa operasi asinkron non-kritis yang perlu dilakukan, tetapi saya tidak ingin menunggu hingga selesai. Dalam implementasi coroutine Tornado, Anda dapat "mengaktifkan & melupakan" fungsi asinkron hanya dengan menghilangkan kata yield
kuncinya.
Saya sudah mencoba mencari cara untuk "mengaktifkan & melupakan" dengan sintaks async
/ baru yang await
dirilis di Python 3.5. Misalnya, cuplikan kode yang disederhanakan:
async def async_foo():
print("Do some stuff asynchronously here...")
def bar():
async_foo() # fire and forget "async_foo()"
bar()
Apa yang terjadi adalah yang bar()
tidak pernah mengeksekusi dan sebagai gantinya kita mendapatkan peringatan runtime:
RuntimeWarning: coroutine 'async_foo' was never awaited
async_foo() # fire and forget "async_foo()"
python
python-3.5
python-asyncio
Mike N
sumber
sumber
Jawaban:
Pembaruan:
Ganti
asyncio.ensure_future
denganasyncio.create_task
everywhere jika Anda menggunakan Python> = 3.7 Ini lebih baru, cara lebih bagus untuk menelurkan tugas .asyncio.Tanyakan untuk "aktifkan dan lupakan"
Menurut dokumentasi python
asyncio.Task
, adalah mungkin untuk memulai beberapa coroutine untuk dieksekusi "di latar belakang" . Tugas yang dibuat olehasyncio.ensure_future
fungsi tidak akan memblokir eksekusi (oleh karena itu fungsi akan segera kembali!). Ini terlihat seperti cara untuk "menembak dan melupakan" seperti yang Anda minta.Keluaran:
Bagaimana jika tugas dijalankan setelah event loop selesai?
Perhatikan bahwa asyncio mengharapkan tugas akan diselesaikan pada saat loop acara selesai. Jadi, jika Anda akan berubah
main()
menjadi:Anda akan mendapatkan peringatan ini setelah program selesai:
Untuk mencegahnya, Anda bisa menunggu semua tugas yang tertunda setelah event loop selesai:
Bunuh tugas alih-alih menunggu mereka
Terkadang Anda tidak ingin menunggu tugas diselesaikan (misalnya, beberapa tugas mungkin dibuat untuk dijalankan selamanya). Dalam hal ini, Anda bisa membatalkannya () daripada menunggunya:
Keluaran:
sumber
stop()
metodenya.Terima kasih Sergey atas jawaban yang berhasil. Ini adalah versi dekorasi yang sama.
Menghasilkan
Catatan: Periksa jawaban saya yang lain yang melakukan hal yang sama menggunakan utas biasa.
sumber
Ini bukan sepenuhnya eksekusi asinkron, tetapi mungkin run_in_executor () cocok untuk Anda.
sumber
executor
default akan meneleponconcurrent.futures.ThreadPoolExecutor.submit()
. Saya sebutkan karena membuat utas tidaklah gratis; api-dan-melupakan 1000 kali per detik mungkin akan memberikan tekanan besar pada manajemen utasUntuk beberapa alasan jika Anda tidak dapat menggunakan
asyncio
maka berikut adalah implementasinya menggunakan thread biasa. Periksa jawaban saya yang lain dan jawaban Sergey juga.sumber