آیندهنماها (Futures)¶
کد منبع: Lib/asyncio/futures.py، Lib/asyncio/base_futures.py
اشیای Future برای پیوند دادن کد سطحپایین مبتنی بر کالبک با کد سطحبالای ناهمگام/await استفاده میشوند.
توابع آیندهنما¶
- asyncio.isfuture(obj)¶
اگر obj یکی از موارد زیر باشد،
Trueرا برمیگرداند:نمونهای از
asyncio.Future،نمونهای از
asyncio.Task،یک شیء شبیه به Future با ویژگی
_asyncio_future_blocking.
اضافه شده در نسخهی 3.5.
- asyncio.ensure_future(obj, *, loop=None)¶
بازگشت:
آرگومان obj را همانگونه که هست، اگر obj یک
Future، یکTask، یا یک شیء شبیه Future باشد (برای آزمون ازisfuture()استفاده میشود.)یک شیء
Taskکه obj را در بر میگیرد، اگر obj یک همروال باشد (برای آزمون ازiscoroutine()استفاده میشود)؛ در این حالت، همروال توسطensure_future()زمانبندی خواهد شد.یک شیء
Taskکه اگر obj قابل await (awaitable) باشد، روی obj await میکند (برای بررسی ازinspect.isawaitable()استفاده میشود.)
اگر obj هیچکدام از موارد بالا نباشد، یک
TypeErrorپرتاب میشود.مهم
برای جلوگیری از ناپدید شدن یک وظیفه در میانهی اجرا، ارجاعی به نتیجهی این تابع ذخیره کنید.
همچنین تابع
create_task()را ببینید که روش ترجیحی برای ایجاد وظایف جدید است، یا ازasyncio.TaskGroupاستفاده کنید که ارجاعی به وظیفه را بهصورت داخلی نگه میدارد.تغییر یافته در نسخهی 3.5.1: این تابع هر شیء awaitable را میپذیرد.
منسوخ شده از نسخهی 3.10: اگر obj یک شیء شبهآیندهنما نباشد و loop مشخص نشده باشد و هیچ حلقه رویدادی در حال اجرا وجود نداشته باشد، هشدار از رده خارج شدن نشان داده میشود.
- asyncio.wrap_future(future, *, loop=None)¶
یک شیء
concurrent.futures.Futureرا در یک شیءasyncio.Futureقرار دهید.منسوخ شده از نسخهی 3.10: اگر future یک شیء شبهآیندهنما نباشد و loop تعیین نشده باشد و هیچ حلقه رویداد در حال اجرا وجود نداشته باشد، هشدار از رده خارج شدن نشان داده میشود.
شیء Future¶
- class asyncio.Future(*, loop=None)¶
یک Future نتیجه نهایی یک عملیات ناهمگام را نشان میدهد. ایمن نسبت به نخ نیست.
Future یک شیء awaitable است. همروالها میتوانند اشیاء Future را تا زمانی که یا نتیجه یا استثنا برای آنها تنظیم شده باشد، یا تا زمانی که لغو شوند، await کنند. یک Future را میتوان چندین بار await کرد و نتیجه یکسان است.
بهطور معمول از Futures استفاده میشود تا امکان تعامل کد سطح پایین مبتنی بر کالبک (برای مثال، در پروتکلهایی که با استفاده از transports asyncio پیادهسازی شدهاند) با کد سطح بالای async/await فراهم شود.
قاعده سرانگشتی این است که هرگز اشیای Future را در APIهای رو به کاربر در معرض قرار ندهید، و روش توصیهشده برای ایجاد یک شیء Future، فراخوانی
loop.create_future()است. به این ترتیب، پیادهسازیهای جایگزین حلقه رویداد میتوانند پیادهسازیهای بهینهشده خود از شیء Future را تزریق کنند.Futures نسبت به نوع نتایج خود عام هستند.
تغییر یافته در نسخهی 3.7: پشتیبانی از ماژول
contextvarsافزوده شد.منسوخ شده از نسخهی 3.10: اگر loop مشخصنشده باشد و هیچ حلقه رویدادی در حال اجرا وجود نداشته باشد، هشدار از رده خارج شدن نشان داده میشود.
- result()¶
نتیجهی Future را برمیگرداند.
اگر Future انجامشده باشد و نتیجهای از طریق متد
set_result()برای آن تنظیم شده باشد، مقدار نتیجه برگردانده میشود.اگر Future انجامشده باشد و استثنایی توسط متد
set_exception()برای آن تنظیم شده باشد، این متد آن استثنا را پرتاب میکند.اگر Future لغوشده باشد، این متد یک استثنای
CancelledErrorپرتاب میکند.اگر نتیجهی Future هنوز در دسترس نباشد، این متد استثانای
InvalidStateErrorرا پرتاب میکند.
- set_result(result)¶
Future را بهعنوان انجامشده علامتگذاری میکند و نتیجهی آن را تنظیم میکند.
اگر Future از قبل انجامشده باشد، خطای
InvalidStateErrorرا پرتاب میکند.
- set_exception(exception)¶
Future را بهعنوان done علامتگذاری میکند و یک استثنا تنظیم میکند.
اگر Future از قبل انجامشده باشد، خطای
InvalidStateErrorرا پرتاب میکند.
- done()¶
اگر Future انجامشده باشد،
Trueبرمیگرداند.یک Future در صورتی انجامشده است که لغوشده باشد یا نتیجه یا استثنایی با فراخوانیهای
set_result()یاset_exception()روی آن تنظیمشده باشد.
- cancelled()¶
اگر Future لغوشده باشد،
Trueرا برمیگرداند.این متد معمولاً برای بررسی این استفاده میشود که یک Future پیش از تنظیم نتیجه یا استثنا برای آن لغونشده باشد:
if not fut.cancelled(): fut.set_result(42)
- add_done_callback(callback, *, context=None)¶
یک کالبک اضافه کنید تا هنگامی که Future انجامشده است اجرا شود.
کالبک با شیء Future بهعنوان تنها آرگومان آن فراخوانی میشود.
اگر Future در زمان فراخوانی این متد از قبل انجامشده باشد، کالبک با
loop.call_soon()زمانبندی میشود.یک آرگومان context اختیاری و فقط کلیدواژهای به شما امکان میدهد یک
contextvars.Contextسفارشی را مشخص کنید تا callback در آن اجرا شود. هنگامی که context ارائه نشود، از زمینهی کنونی استفاده میشود.میتوان از
functools.partial()برای ارسال پارامترها به کالبک استفاده کرد، برای مثال:# Call 'print("Future:", fut)' when "fut" is done. fut.add_done_callback( functools.partial(print, "Future:"))
تغییر یافته در نسخهی 3.7: پارامتر context که فقط کلیدواژهای است، اضافه شد. برای جزئیات بیشتر، PEP 567 را ببینید.
- remove_done_callback(callback)¶
callback را از فهرست کالبکها حذف کنید.
تعداد کالبکهای حذفشده را برمیگرداند، که معمولاً ۱ است، مگر اینکه یک کالبک بیش از یک بار افزوده شده باشد.
- cancel(msg=None)¶
Future را لغو میکند و کالبکها را زمانبندی میکند.
اگر Future از قبل done یا cancelled باشد،
Falseرا برمیگرداند. در غیر این صورت، وضعیت Future را به cancelled تغییر میدهد، کالبکها را زمانبندی میکند وTrueرا برمیگرداند.آرگومان اختیاری رشتهای msg بهعنوان آرگومان به استثنای
CancelledErrorارسال میشود؛ این استثنا هنگامی پرتاب میشود که یک Future لغوشده await شود.تغییر یافته در نسخهی 3.9: پارامتر msg افزوده شد.
- exception()¶
استثنایی را که روی این Future تنظیم شده است، برمیگرداند.
استثنا (یا
Noneاگر استثنایی تنظیم نشده باشد) تنها در صورتی برگردانده میشود که Future انجامشده باشد.اگر Future لغوشده باشد، این متد یک استثنای
CancelledErrorپرتاب میکند.اگر Future هنوز انجامشده نیست، این متد استثنای
InvalidStateErrorرا پرتاب میکند.
- get_loop()¶
حلقه رویدادی را که شیء Future به آن متصل است، برمیگرداند.
اضافه شده در نسخهی 3.7.
این مثال یک شیء Future ایجاد میکند، یک Task ناهمگام را ایجاد و زمانبندی میکند تا نتیجه را برای Future تنظیم کند، و منتظر میماند تا Future نتیجه داشته باشد:
async def set_after(fut, delay, value):
# Sleep for *delay* seconds.
await asyncio.sleep(delay)
# Set *value* as a result of *fut* Future.
fut.set_result(value)
async def main():
# Get the current event loop.
loop = asyncio.get_running_loop()
# Create a new Future object.
fut = loop.create_future()
# Run "set_after()" coroutine in a parallel Task.
# We are using the low-level "loop.create_task()" API here because
# we already have a reference to the event loop at hand.
# Otherwise we could have just used "asyncio.create_task()".
loop.create_task(
set_after(fut, 1, '... world'))
print('hello ...')
# Wait until *fut* has a result (1 second) and print it.
print(await fut)
asyncio.run(main())
مهم
شیء Future بهگونهای طراحی شده است که از concurrent.futures.Future تقلید کند. تفاوتهای اصلی عبارتند از:
برخلاف Futureهای asyncio، نمونههای
concurrent.futures.Futureرا نمیتوان await کرد.asyncio.Future.result()وasyncio.Future.exception()آرگومان timeout را نمیپذیرند.asyncio.Future.result()وasyncio.Future.exception()زمانی که Future انجامشده نباشد، استثنایInvalidStateErrorرا پرتاب میکنند.کالبکهای ثبتشده با
asyncio.Future.add_done_callback()بلافاصله فراخوانی نمیشوند. در عوض، باloop.call_soon()زمانبندی میشوند.Future در asyncio با توابع
concurrent.futures.wait()وconcurrent.futures.as_completed()سازگار نیست.asyncio.Future.cancel()یک آرگومان اختیاریmsgرا میپذیرد، اماconcurrent.futures.Future.cancel()نمیپذیرد.