آینده‌نماها (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 تقلید کند. تفاوت‌های اصلی عبارتند از: