حلقه رویداد

کد منبع: Lib/asyncio/events.py, Lib/asyncio/base_events.py


پیشگفتار

حلقه‌ی رویداد، هسته‌ی هر برنامه‌ی asyncio است. حلقه‌های رویداد، وظایف ناهمگام و کال‌بک‌ها را اجرا می‌کنند، عملیات ورودی/خروجی شبکه را انجام می‌دهند و زیرفرایندها را اجرا می‌کنند.

توسعه‌دهندگان برنامه باید معمولاً از توابع سطح بالای asyncio، مانند asyncio.run()، استفاده کنند و به‌ندرت نیاز است که به شیء حلقه ارجاع دهند یا متدهای آن را فراخوانی کنند. این بخش عمدتاً برای نویسندگان کد، کتابخانه‌ها و چارچوب‌های سطح پایین‌تر در نظر گرفته شده است که به کنترل دقیق‌تری بر رفتار حلقه رویداد نیاز دارند.

به دست آوردن حلقه رویداد

می‌توان از توابع سطح پایین زیر برای دریافت، تنظیم یا ایجاد یک حلقه رویداد استفاده کرد:

asyncio.get_running_loop()

حلقه رویداد در حال اجرا را در نخ سیستم‌عامل فعلی برمی‌گرداند.

اگر هیچ حلقه رویدادی در حال اجرا نباشد، یک RuntimeError پرتاب می‌شود.

این تابع را فقط می‌توان از یک هم‌روال یا کال‌بک فراخوانی کرد.

اضافه شده در نسخه‌ی 3.7.

asyncio.get_event_loop()

حلقه‌ی رویداد جاری را دریافت کنید.

هنگامی که از یک هم‌روال یا کال‌بک (مثلاً زمان‌بندی‌شده با call_soon یا API مشابه) فراخوانی شود، این تابع همیشه حلقه رویداد در حال اجرا را برمی‌گرداند.

اگر هیچ حلقه‌ی رویداد در حال اجرا تنظیم‌نشده باشد، تابع نتیجه‌ی فراخوانی get_event_loop_policy().get_event_loop() را برمی‌گرداند.

از آنجا که این تابع رفتار نسبتاً پیچیده‌ای دارد (به‌ویژه زمانی که از سیاست‌های سفارشی حلقه رویداد استفاده می‌شود)، در هم‌روال‌ها و کال‌بک‌ها استفاده از تابع get_running_loop() به get_event_loop() ترجیح داده می‌شود.

همان‌طور که در بالا اشاره شد، به‌جای استفاده از این توابع سطح پایین برای ایجاد و بستن دستی حلقه رویداد، استفاده از تابع سطح بالاتر asyncio.run() را در نظر بگیرید.

تغییر یافته در نسخه‌ی 3.14: اگر حلقه رویداد جاری وجود نداشته باشد، یک RuntimeError پرتاب می‌شود.

توجه

سیستم سیاست‌گذاری asyncio منسوخ شده است و در Python 3.16 حذف خواهد شد؛ از آن پس، این تابع در صورت وجود، حلقه رویداد در حال اجرای فعلی را برمی‌گرداند، در غیر این صورت حلقه تنظیم‌شده توسط set_event_loop() را برمی‌گرداند.

asyncio.set_event_loop(loop)

loop را به‌عنوان حلقه رویداد جاری برای نخ جاری سیستم‌عامل تنظیم می‌کند.

asyncio.new_event_loop()

یک شیء حلقه رویداد جدید ایجاد و برمی‌گرداند.

توجه داشته باشید که رفتار توابع get_event_loop()، set_event_loop() و new_event_loop() می‌تواند با تنظیم یک سیاست حلقه رویداد سفارشی تغییر کند.

فهرست

این صفحه‌ی مستندات شامل بخش‌های زیر است:

متدهای حلقه رویداد

حلقه‌های رویداد APIهای سطح پایین برای موارد زیر دارند:

اجرا و توقف حلقه

loop.run_until_complete(future)

تا کامل شدن future (نمونه‌ای از Future) اجرا کنید.

اگر آرگومان یک شیء هم‌روال باشد، به‌طور ضمنی برای اجرا به‌عنوان یک asyncio.Task زمان‌بندی می‌شود.

نتیجه‌ی Future را برمی‌گرداند یا استثنای آن را پرتاب می‌کند.

loop.run_forever()

حلقه رویداد را تا زمانی که stop() فراخوانی شود، اجرا کنید.

اگر stop() پیش از فراخوانی run_forever() فراخوانی شود، حلقه انتخابگر I/O را یک بار با مهلت صفر پایش می‌کند، تمام کال‌بک‌های برنامه‌ریزی‌شده در پاسخ به رویدادهای I/O (و آن‌هایی که از قبل برنامه‌ریزی‌شده بودند) را اجرا می‌کند و سپس خارج می‌شود.

اگر stop() در حالی که run_forever() در حال اجرا است فراخوانی شود، حلقه دسته فعلی کال‌بک‌ها را اجرا می‌کند و سپس خارج می‌شود. توجه داشته باشید که کال‌بک‌های جدیدی که توسط کال‌بک‌ها زمان‌بندی شده‌اند، در این حالت اجرا نخواهند شد؛ در عوض، آن‌ها بار بعدی که run_forever() یا run_until_complete() فراخوانی شود، اجرا خواهند شد.

loop.stop()

حلقه رویداد را متوقف کنید.

loop.is_running()

اگر حلقه رویداد هم‌اکنون در حال اجرا باشد، True را برمی‌گرداند.

loop.is_closed()

اگر حلقه رویداد بسته شده باشد، True را برمی‌گرداند.

loop.close()

حلقه رویداد را ببندید.

هنگامی که این تابع فراخوانی می‌شود، حلقه نباید در حال اجرا باشد. تمام کال‌بک‌های در انتظار دور ریخته می‌شوند.

این متد همه صف‌ها را پاک می‌کند و اجراکننده (executor) را خاموش می‌کند، اما منتظر پایان اجراکننده نمی‌ماند.

این متد هم‌توان (idempotent) و بازگشت‌ناپذیر است. پس از بسته شدن حلقه رویداد، نباید متدهای دیگری فراخوانی شوند.

async loop.shutdown_asyncgens()

تمام اشیای asynchronous generator را که در حال حاضر باز هستند، برای بسته‌شدن با فراخوانی aclose() زمان‌بندی می‌کند. پس از فراخوانی این متد، در صورت پیمایش یک تولیدگر ناهمگام جدید، حلقه رویداد هشداری نشان خواهد داد. باید از این برای نهایی‌سازی قابل‌اطمینان تمام تولیدگرهای ناهمگام زمان‌بندی‌شده استفاده شود.

توجه داشته باشید که هنگامی که از asyncio.run() استفاده می‌شود، نیازی به فراخوانی این تابع نیست.

مثال:

try:
    loop.run_forever()
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

اضافه شده در نسخه‌ی 3.6.

async loop.shutdown_default_executor(timeout=None)

بستن اجراکننده‌ی پیش‌فرض را زمان‌بندی می‌کند و منتظر می‌ماند تا همه‌ی نخ‌های موجود در ThreadPoolExecutor join شوند. پس از فراخوانی این متد، استفاده از اجراکننده‌ی پیش‌فرض با loop.run_in_executor() باعث پرتاب یک RuntimeError خواهد شد.

پارامتر timeout مدت زمانی را مشخص می‌کند (بر حسب ثانیه از نوع float) که به اجراکننده (executor) برای اتمام پیوستن (joining) داده می‌شود. با مقدار پیش‌فرض None، به اجراکننده زمان نامحدودی داده می‌شود.

در صورت رسیدن به timeout، یک RuntimeWarning نشان داده می‌شود و اجراکننده پیش‌فرض بدون انتظار برای اتمام پیوستن (joining) نخ‌های آن خاتمه داده می‌شود.

توجه

هنگام استفاده از asyncio.run()، این متد را فراخوانی نکنید، زیرا این تابع خاموش کردن اجراکننده (executor) پیش‌فرض را به‌صورت خودکار مدیریت می‌کند.

اضافه شده در نسخه‌ی 3.9.

تغییر یافته در نسخه‌ی 3.12: پارامتر timeout افزوده شد.

زمان‌بندی کال‌بک‌ها

loop.call_soon(callback, *args, context=None)

callback کال‌بک را زمان‌بندی کنید تا در تکرار بعدی حلقه رویداد با آرگومان‌های args فراخوانی شود.

یک نمونه از asyncio.Handle برمی‌گرداند، که بعداً می‌توان از آن برای لغو کال‌بک استفاده کرد.

کال‌بک‌ها به همان ترتیبی که ثبت شده‌اند فراخوانی می‌شوند. هر کال‌بک دقیقاً یک بار فراخوانی خواهد شد.

آرگومان context که اختیاری و فقط کلیدواژه‌ای است، یک contextvars.Context سفارشی را مشخص می‌کند تا callback در آن اجرا شود. در صورتی که context ارائه نشود، کال‌بک‌ها از زمینه‌ی جاری استفاده می‌کنند.

برخلاف call_soon_threadsafe()، این متد ایمن از نظر نخ نیست.

loop.call_soon_threadsafe(callback, *args, context=None)

یک گونه‌ی نخ‌ایمن از call_soon(). هنگام زمان‌بندی کال‌بک‌ها از یک نخ دیگر، این تابع باید استفاده شود، زیرا call_soon() نخ‌ایمن نیست.

فراخوانی این تابع از یک زمینه‌ی بازورودپذیر (reentrant context) یا مدیر سیگنال ایمن است؛ با این حال، استفاده از دسته‌ی برگردانده‌شده در چنین زمینه‌هایی ایمن یا مفید نیست.

اگر روی حلقه‌ای که بسته شده است فراخوانی شود، RuntimeError پرتاب می‌شود. این اتفاق ممکن است در یک نخ ثانویه هنگامی که برنامه اصلی در حال خاموش شدن است رخ دهد.

بخش همروندی و چندنخی مستندات را ببینید.

تغییر یافته در نسخه‌ی 3.7: پارامتر فقط کلیدواژه‌ای context اضافه شد. برای جزئیات بیشتر PEP 567 را ببینید.

توجه

بیشتر توابع زمان‌بندی asyncio اجازه‌ی ارسال آرگومان‌های کلیدواژه‌ای را نمی‌دهند. برای این کار، از functools.partial() استفاده کنید:

# will schedule "print("Hello", flush=True)"
loop.call_soon(
    functools.partial(print, "Hello", flush=True))

استفاده از اشیاء partial معمولاً راحت‌تر از استفاده از لامبداها است، زیرا asyncio می‌تواند اشیاء partial را بهتر در پیام‌های اشکال‌زدایی و خطا نمایش دهد.

زمان‌بندی کال‌بک‌های تأخیری

حلقه رویداد سازوکارهایی را برای زمان‌بندی توابع کال‌بک فراهم می‌کند تا در زمانی در آینده فراخوانی شوند. حلقه رویداد از ساعت‌های یکنواخت برای پیگیری زمان استفاده می‌کند.

loop.call_later(delay, callback, *args, context=None)

فراخوانی callback را پس از delay ثانیه زمان‌بندی می‌کند (این مقدار می‌تواند عدد صحیح یا اعشاری باشد).

یک نمونه از asyncio.TimerHandle بازگردانده می‌شود که می‌توان از آن برای لغو کال‌بک استفاده کرد.

کال‌بک دقیقاً یک بار فراخوانی می‌شود. اگر دو کال‌بک برای زمان دقیقاً یکسانی زمان‌بندی شده باشند، ترتیب فراخوانی آن‌ها تعریف‌نشده است.

آرگومان‌های جایگاهی اختیاری args هنگام فراخوانی کال‌بک به آن فرستاده می‌شوند. برای فرستادن آرگومان‌های کلیدواژه‌ای به callback از functools.partial() برای فرستادن آرگومان‌های کلیدواژه‌ای استفاده کنید.

آرگومان اختیاری فقط کلیدواژه‌ای context، امکان تعیین یک contextvars.Context سفارشی را فراهم می‌کند تا callback در آن اجرا شود. در صورتی که context ارائه نشود، از زمینه فعلی استفاده می‌شود.

توجه

برای کارایی، کال‌بک‌های زمان‌بندی‌شده با loop.call_later() ممکن است تا یک دقت ساعت زودتر اجرا شوند (به time.get_clock_info('monotonic').resolution مراجعه کنید).

تغییر یافته در نسخه‌ی 3.7: پارامتر فقط کلیدواژه‌ای context اضافه شد. برای جزئیات بیشتر PEP 567 را ببینید.

تغییر یافته در نسخه‌ی 3.8: در پایتون 3.7 و نسخه‌های پیش‌تر، با پیاده‌سازی پیش‌فرض حلقه رویداد، delay نمی‌توانست بیشتر از یک روز باشد. این مشکل در پایتون 3.8 برطرف شده است.

loop.call_at(when, callback, *args, context=None)

callback را زمان‌بندی کنید تا در برچسب زمانی مطلق داده‌شده when (یک int یا float) فراخوانی شود، با استفاده از همان مرجع زمانی loop.time().

رفتار این متد همانند call_later() است.

یک نمونه از asyncio.TimerHandle بازگردانده می‌شود که می‌توان از آن برای لغو کال‌بک استفاده کرد.

توجه

برای کارایی، ممکن است کال‌بک‌های زمان‌بندی‌شده با loop.call_at() تا یک تفکیک‌پذیری ساعت زودتر اجرا شوند (به time.get_clock_info('monotonic').resolution مراجعه کنید).

تغییر یافته در نسخه‌ی 3.7: پارامتر فقط کلیدواژه‌ای context اضافه شد. برای جزئیات بیشتر PEP 567 را ببینید.

تغییر یافته در نسخه‌ی 3.8: در پایتون 3.7 و نسخه‌های پیشین، در پیاده‌سازی پیش‌فرض حلقه رویداد، تفاوت میان when و زمان جاری نمی‌توانست بیش از یک روز باشد. این مورد در پایتون 3.8 اصلاح شده است.

loop.time()

زمان جاری را به‌عنوان یک مقدار float، بر اساس ساعت یکنواخت داخلی حلقه رویداد برمی‌گرداند.

توجه

تغییر یافته در نسخه‌ی 3.8: در پایتون 3.7 و نسخه‌های پیش از آن، مهلت‌های زمانی (delay نسبی یا when مطلق) نباید از یک روز بیشتر باشند. این مورد در پایتون 3.8 اصلاح شده است.

همچنین ملاحظه نمائید

تابع asyncio.sleep().

ایجاد آینده‌نماها و وظایف

loop.create_future()

یک شیء asyncio.Future متصل به حلقه رویداد ایجاد کنید.

این، روش ارجح برای ایجاد Futures در asyncio است. این روش به حلقه‌های رویداد شخص ثالث امکان می‌دهد پیاده‌سازی‌های جایگزینی از شیء Future را ارائه کنند (با کارایی بهتر یا ابزاربندی (instrumentation)).

اضافه شده در نسخه‌ی 3.5.2.

loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)

اجرای هم‌روال coro را زمان‌بندی می‌کند. یک شیء Task را برمی‌گرداند.

حلقه‌های رویداد شخص ثالث می‌توانند برای تعامل‌پذیری از زیرکلاس اختصاصی خود از Task استفاده کنند. در این حالت، نوع نتیجه یک زیرکلاس از Task است.

امضای کامل تابع تا حد زیادی مشابه امضای سازنده‌ی Task (یا کارخانه) است؛ تمام آرگومان‌های کلیدواژه‌ای این تابع به آن رابط منتقل می‌شوند.

اگر آرگومان name ارائه شده باشد و None نباشد، به‌عنوان نام وظیفه با استفاده از Task.set_name() تنظیم می‌شود.

یک آرگومان context اختیاری و فقط کلیدواژه‌ای امکان تعیین یک contextvars.Context سفارشی را فراهم می‌کند تا coro در آن اجرا شود. در صورتی که context ارائه نشود، یک کپی از زمینه جاری ایجاد می‌شود.

یک آرگومان اختیاری فقط کلیدواژه‌ای eager_start به شما امکان می‌دهد مشخص کنید که وظیفه باید در حین فراخوانی create_task بلافاصله اجرا شود یا بعداً زمان‌بندی شود. اگر eager_start ارسال نشود، حالت تنظیم‌شده توسط loop.set_task_factory() استفاده خواهد شد.

تغییر یافته در نسخه‌ی 3.8: پارامتر name افزوده شد.

تغییر یافته در نسخه‌ی 3.11: پارامتر context افزوده شد.

تغییر یافته در نسخه‌ی 3.13.3: kwargs افزوده شد که پارامترهای اضافی دلخواه، از جمله name و context را منتقل می‌کند.

تغییر یافته در نسخه‌ی 3.13.4: تغییری که name و context را (اگر None باشد) منتقل می‌کرد، بازگردانده شد، در حالی که همچنان سایر آرگومان‌های کلیدواژه‌ای دلخواه منتقل می‌شوند (برای جلوگیری از از بین رفتن سازگاری با نسخه‌ی پیشین 3.13.3).

تغییر یافته در نسخه‌ی 3.14: اکنون همه‌ی kwargs منتقل می‌شوند. پارامتر eager_start با کارخانه‌های وظیفه‌ی مشتاق (eager task factories) کار می‌کند.

loop.set_task_factory(factory)

یک کارخانه‌ی وظیفه (task factory) تنظیم کنید که loop.create_task() از آن استفاده خواهد کرد.

اگر factory برابر None باشد، کارخانه وظیفه پیش‌فرض تنظیم خواهد شد. در غیر این صورت، factory باید یک شیء فراخوانی‌پذیر با امضایی مطابق با (loop, coro, **kwargs) باشد، که در آن loop مرجعی به حلقه رویداد فعال و coro یک شیء هم‌روال است. این شیء فراخوانی‌پذیر باید تمام kwargs را منتقل کند و شیءای سازگار با asyncio.Task برگرداند.

تغییر یافته در نسخه‌ی 3.13.3: لازم است که تمام kwargs به asyncio.Task منتقل شوند.

تغییر یافته در نسخه‌ی 3.13.4: دیگر name به کارخانه‌های وظیفه (task factories) ارسال نمی‌شود. اگر context برابر None باشد، دیگر به کارخانه‌های وظیفه (task factories) ارسال نمی‌شود.

تغییر یافته در نسخه‌ی 3.14: name و context اکنون دوباره به‌صورت غیرشرطی به کارخانه‌های task پاس داده می‌شوند.

loop.get_task_factory()

یک کارخانه وظیفه (task factory) برمی‌گرداند، یا اگر از کارخانه پیش‌فرض استفاده شود، None برمی‌گرداند.

باز کردن اتصالات شبکه

async loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)

باز کردن یک اتصال انتقال جریانی به نشانی مشخص‌شده با host و port.

خانواده سوکت می‌تواند، بسته به host (یا آرگومان family، در صورت ارائه)، یا AF_INET یا AF_INET6 باشد.

نوع سوکت SOCK_STREAM خواهد بود.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی از پروتکل asyncio را برمی‌گرداند.

این متد تلاش خواهد کرد اتصال را در پس‌زمینه برقرار کند. در صورت موفقیت، یک جفت (transport, protocol) برمی‌گرداند.

خلاصه‌ای از ترتیب زمانی عملیات زیربنایی به شرح زیر است:

  1. اتصال برقرار می‌شود و یک transport برای آن ایجاد می‌شود.

  2. protocol_factory بدون آرگومان فراخوانی می‌شود و انتظار می‌رود نمونه‌ای از protocol را برگرداند.

  3. نمونه‌ی پروتکل با فراخوانی متد connection_made() خود، به انتقال متصل می‌شود.

  4. در صورت موفقیت، یک تاپل (transport, protocol) برگردانده می‌شود.

انتقال ایجادشده، یک جریان دوطرفه وابسته به پیاده‌سازی است.

آرگومان‌های دیگر:

  • ssl: اگر داده شده باشد و false نباشد، یک انتقال SSL/TLS ایجاد می‌شود (به‌طور پیش‌فرض یک انتقال TCP ساده ایجاد می‌شود). اگر ssl یک شیء ssl.SSLContext باشد، از این زمینه برای ایجاد انتقال استفاده می‌شود؛ اگر ssl True باشد، از یک زمینه پیش‌فرض که از ssl.create_default_context() بازگشت داده می‌شود، استفاده می‌شود.

    همچنین ملاحظه نمائید

    ملاحظات امنیتی SSL/TLS

  • server_hostname نام میزبانی را که گواهی سرور هدف با آن تطبیق داده خواهد شد، تنظیم یا جایگزین می‌کند. این مقدار باید فقط در صورتی ارسال شود که ssl برابر None نباشد. به‌طور پیش‌فرض، از مقدار آرگومان host استفاده می‌شود. اگر host خالی باشد، مقدار پیش‌فرضی وجود ندارد و شما باید مقداری برای server_hostname ارسال کنید. اگر server_hostname یک رشته خالی باشد، تطبیق نام میزبان غیرفعال می‌شود (که یک خطر امنیتی جدی است و امکان حملات مرد میانی بالقوه را فراهم می‌کند).

  • family، proto و flags خانواده‌ی آدرس، پروتکل و پرچم‌های اختیاری هستند که برای تفکیک host به getaddrinfo() ارسال می‌شوند. اگر داده شوند، همه‌ی این‌ها باید اعداد صحیحی از ثابت‌های متناظر ماژول socket باشند.

  • happy_eyeballs_delay، در صورت ارائه، Happy Eyeballs را برای این اتصال فعال می‌کند. این باید یک عدد ممیز شناور باشد که مدت‌زمان به ثانیه برای انتظار جهت کامل شدن یک تلاش برای اتصال، پیش از آغاز تلاش بعدی به‌صورت موازی را نشان می‌دهد. این همان «Connection Attempt Delay» است که در RFC 8305 تعریف شده است. مقدار پیش‌فرض معقولی که RFC توصیه کرده است، 0.25 (۲۵۰ میلی‌ثانیه) است.

  • interleave بازچینش نشانی‌ها را هنگامی که یک نام میزبان به چند نشانی IP حل می‌شود، کنترل می‌کند. اگر 0 باشد یا مشخص‌نشده باشد، هیچ بازچینشی انجام نمی‌شود و نشانی‌ها به همان ترتیبی که getaddrinfo() آن‌ها را برمی‌گرداند امتحان می‌شوند. اگر یک عدد صحیح مثبت مشخص شود، نشانی‌ها بر اساس خانواده‌ی نشانی به‌صورت میان‌بافت (interleaved) چیده می‌شوند و عدد صحیح داده‌شده به‌عنوان «تعداد اولین خانواده‌ی نشانی (First Address Family Count)» تعریف‌شده در RFC 8305 تفسیر می‌شود. مقدار پیش‌فرض در صورتی که happy_eyeballs_delay مشخص‌نشده باشد 0 و در صورتی که مشخص‌شده باشد 1 است.

  • sock، در صورت ارائه، باید یک شیء socket.socket موجود و از پیش متصل باشد تا توسط انتقال استفاده شود. اگر sock ارائه شده باشد، نباید هیچ‌کدام از host، port، family، proto، flags، happy_eyeballs_delay، interleave و local_addr مشخص شوند.

    توجه

    آرگومان sock مالکیت سوکت را به ترابری ایجادشده منتقل می‌کند. برای بستن سوکت، متد close() همان ترابری را فراخوانی کنید.

  • local_addr، در صورت ارائه، یک تاپل (local_host, local_port) است که برای مقید کردن سوکت به‌صورت محلی استفاده می‌شود. local_host و local_port نیز مانند host و port با استفاده از getaddrinfo() جستجو می‌شوند.

  • ssl_handshake_timeout (برای یک اتصال TLS) مدت‌زمانی به ثانیه است که باید پیش از لغو اتصال، برای تکمیل دست‌دهی TLS (TLS handshake) منتظر ماند. در صورت None بودن، 60.0 ثانیه است (پیش‌فرض).

  • ssl_shutdown_timeout زمان انتظار بر حسب ثانیه برای کامل شدن خاموشی SSL (SSL shutdown) پیش از قطع اتصال است. اگر None (پیش‌فرض) باشد، 30.0 ثانیه است.

  • all_errors تعیین می‌کند که وقتی نمی‌توان یک اتصال ایجاد کرد، چه استثناهایی پرتاب می‌شوند. به‌طور پیش‌فرض، فقط یک Exception واحد پرتاب می‌شود: اولین استثنا اگر فقط یکی وجود داشته باشد یا همه‌ی خطاها پیام یکسانی داشته باشند، یا یک OSError واحد با پیام‌های خطای ترکیب‌شده. وقتی all_errors برابر True باشد، یک ExceptionGroup پرتاب خواهد شد که شامل همه‌ی استثناها می‌شود (حتی اگر فقط یکی وجود داشته باشد).

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از SSL/TLS در ProactorEventLoop افزوده شد.

تغییر یافته در نسخه‌ی 3.6: گزینه‌ی سوکت socket.TCP_NODELAY به‌طور پیش‌فرض برای تمام اتصالات TCP تنظیم شده است.

تغییر یافته در نسخه‌ی 3.7: پارامتر ssl_handshake_timeout اضافه شد.

تغییر یافته در نسخه‌ی 3.8: پارامترهای happy_eyeballs_delay و interleave افزوده شدند.

الگوریتم Happy Eyeballs: موفقیت با میزبان‌های دو پشته‌ای. هنگامی که مسیر و پروتکل IPv4 یک سرور کار می‌کنند، اما مسیر و پروتکل IPv6 آن سرور کار نمی‌کنند، یک برنامه کلاینت دو پشته‌ای در مقایسه با یک کلاینت فقط IPv4 با تأخیر قابل‌توجهی در اتصال مواجه می‌شود. این وضعیت نامطلوب است، زیرا باعث می‌شود کلاینت دو پشته‌ای تجربه کاربری بدتری داشته باشد. این سند الزامات الگوریتم‌هایی را که این تأخیر قابل‌مشاهده برای کاربر را کاهش می‌دهند، مشخص می‌کند و یک الگوریتم ارائه می‌دهد.

برای اطلاعات بیشتر: https://datatracker.ietf.org/doc/html/rfc6555

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

تغییر یافته در نسخه‌ی 3.12: all_errors افزوده شد.

همچنین ملاحظه نمائید

تابع open_connection() یک API جایگزین سطح‌بالا است. این تابع یک جفت (StreamReader، StreamWriter) را برمی‌گرداند که می‌توان مستقیماً در کد async/await از آن‌ها استفاده کرد.

async loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_port=None, allow_broadcast=None, sock=None)

یک اتصال دیتاگرام ایجاد کنید.

خانواده سوکت می‌تواند یکی از AF_INET، AF_INET6 یا AF_UNIX باشد، بسته به host (یا آرگومان family، در صورت ارائه).

نوع سوکت برابر با SOCK_DGRAM خواهد بود.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی پروتکل را برمی‌گرداند.

در صورت موفقیت، یک تاپل از (transport, protocol) برگردانده می‌شود.

آرگومان‌های دیگر:

  • local_addr، در صورت ارائه، یک تاپل (local_host, local_port) است که برای پیوند دادن سوکت به‌صورت محلی استفاده می‌شود. local_host و local_port با استفاده از getaddrinfo() جستجو می‌شوند.

    توجه

    در ویندوز، هنگام استفاده از حلقه رویداد proactor با local_addr=None، در زمان اجرا یک OSError با errno.WSAEINVAL پرتاب می‌شود.

  • remote_addr، در صورت ارائه، یک تاپل به شکل (remote_host, remote_port) است که برای اتصال سوکت به یک نشانی دوردست استفاده می‌شود. remote_host و remote_port با استفاده از getaddrinfo() جستجو می‌شوند.

  • family، proto و flags خانواده‌ی نشانی، پروتکل و پرچم‌های اختیاری هستند که باید برای وضوح host به getaddrinfo() ارسال شوند. در صورت ارائه، همه‌ی این موارد باید اعداد صحیحی از ثابت‌های متناظر ماژول socket باشند.

  • reuse_port به هسته می‌گوید که اجازه دهد این پایانه به همان پورتی متصل شود که سایر پایانه‌های موجود به آن متصل هستند، مشروط بر اینکه همه‌ی آن‌ها این پرچم را هنگام ایجاد تنظیم کنند. این گزینه در ویندوز و برخی یونیکس‌ها پشتیبانی نمی‌شود. اگر ثابت socket.SO_REUSEPORT تعریف نشده باشد، این قابلیت پشتیبانی نمی‌شود.

  • allow_broadcast به هسته می‌گوید که به این پایانه اجازه دهد پیام‌ها را به نشانی پخش (broadcast address) ارسال کند.

  • sock می‌تواند به‌صورت اختیاری مشخص شود تا از یک شیء socket.socket از پیش موجود و متصل‌شده توسط انتقال استفاده شود. در صورت مشخص شدن، local_addr و remote_addr باید حذف شوند (باید None باشند).

    توجه

    آرگومان sock مالکیت سوکت را به ترابری ایجادشده منتقل می‌کند. برای بستن سوکت، متد close() همان ترابری را فراخوانی کنید.

مثال‌های پروتکل کلاینت اکو UDP و پروتکل سرور اکو UDP را ببینید.

تغییر یافته در نسخه‌ی 3.4.4: پارامترهای family، proto، flags، reuse_address، reuse_port، allow_broadcast و sock افزوده شده‌اند.

تغییر یافته در نسخه‌ی 3.8: پشتیبانی از ویندوز اضافه شد.

تغییر یافته در نسخه‌ی 3.8.1: پارامتر reuse_address دیگر پشتیبانی نمی‌شود، زیرا استفاده از socket.SO_REUSEADDR یک نگرانی امنیتی جدی برای UDP به همراه دارد. ارسال صریح reuse_address=True منجر به پرتاب استثنا خواهد شد.

وقتی چندین فرایند با UIDهای متفاوت، با SO_REUSEADDR سوکت‌ها را به یک آدرس سوکت UDP یکسان اختصاص می‌دهند، بسته‌های ورودی ممکن است به‌صورت تصادفی بین سوکت‌ها توزیع شوند.

در پلتفرم‌های پشتیبانی‌شده، می‌توان از reuse_port به‌عنوان جایگزینی برای عملکرد مشابه استفاده کرد. با reuse_port، به‌جای آن از socket.SO_REUSEPORT استفاده می‌شود، که به‌طور مشخص از اختصاص دادن سوکت‌ها به یک آدرس سوکت یکسان توسط فرآیندهایی با UIDهای متفاوت جلوگیری می‌کند.

تغییر یافته در نسخه‌ی 3.11: پارامتر reuse_address که از پایتون 3.8.1، 3.7.6 و 3.6.10 غیرفعال شده بود، به‌طور کامل حذف شده است.

async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

ایجاد یک اتصال Unix.

خانواده سوکت AF_UNIX خواهد بود؛ نوع سوکت SOCK_STREAM خواهد بود.

در صورت موفقیت، یک تاپل از (transport, protocol) برگردانده می‌شود.

path نام یک سوکت دامنه‌ی یونیکس است و الزامی است، مگر اینکه پارامتر sock مشخص شده باشد. از سوکت‌های انتزاعی یونیکس و مسیرهای str، bytes و Path پشتیبانی می‌شود.

برای اطلاعات درباره آرگومان‌های این متد، مستندات متد loop.create_connection() را ببینید.

تغییر یافته در نسخه‌ی 3.7: پارامتر ssl_handshake_timeout اضافه شد. پارامتر path اکنون می‌تواند یک path-like object باشد.

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

ایجاد سرورهای شبکه

async loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)

یک سرور TCP (نوع سوکت SOCK_STREAM) ایجاد کنید که روی port از آدرس host گوش می‌دهد.

یک شیء Server برمی‌گرداند.

آرگومان‌ها:

  • protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی پروتکل را برمی‌گرداند.

  • پارامتر host را می‌توان روی چندین نوع تنظیم کرد که تعیین می‌کنند سرور در کجا گوش می‌دهد:

    • اگر host یک رشته باشد، سرور TCP به یک رابط شبکه واحد که توسط host مشخص شده است، مقید می‌شود.

    • اگر host دنباله‌ای از رشته‌ها باشد، سرور TCP به همه رابط‌های شبکه مشخص‌شده توسط آن دنباله مقید می‌شود.

    • اگر host یک رشته خالی یا None باشد، همه رابط‌ها در نظر گرفته می‌شوند و فهرستی از چندین سوکت برگردانده می‌شود (به احتمال زیاد یکی برای IPv4 و دیگری برای IPv6).

  • می‌توان پارامتر port را برای مشخص کردن پورتی که سرور باید روی آن گوش دهد تنظیم کرد. اگر 0 یا None (پیش‌فرض) باشد، یک پورت تصادفی استفاده‌نشده انتخاب خواهد شد (توجه داشته باشید که اگر host به چند رابط شبکه تفکیک شود، برای هر رابط یک پورت تصادفی متفاوت انتخاب خواهد شد).

  • family می‌تواند روی socket.AF_INET یا AF_INET6 تنظیم شود تا سوکت را وادار به استفاده از IPv4 یا IPv6 کند. اگر تنظیم نشود، family بر اساس نام میزبان تعیین می‌شود (پیش‌فرض AF_UNSPEC است).

  • flags یک نقاب بیتی (bitmask) برای getaddrinfo() است.

  • sock را می‌توان به‌صورت اختیاری برای استفاده از یک شیء سوکت از پیش موجود تعیین کرد. اگر تعیین شود، host و port نباید تعیین شوند.

    توجه

    آرگومان sock مالکیت سوکت را به سرور ایجادشده منتقل می‌کند. برای بستن سوکت، متد close() سرور را فراخوانی کنید.

  • backlog حداکثر تعداد اتصال‌های در صف است که به listen() داده می‌شود (پیش‌فرض ۱۰۰ است).

  • ssl را می‌توان به یک نمونه از SSLContext تنظیم کرد تا TLS روی اتصال‌های پذیرفته‌شده فعال شود.

  • reuse_address به هسته می‌گوید که از یک سوکت محلی در وضعیت TIME_WAIT دوباره استفاده کند، بدون این‌که منتظر پایان مهلت زمانی طبیعی آن بماند. اگر تعیین‌نشده باشد، در Unix به‌طور خودکار روی True تنظیم خواهد شد.

  • reuse_port به هسته می‌گوید که اجازه دهد این پایانه به همان پورتی که سایر پایانه‌های موجود به آن مقید شده‌اند، مقید شود، مشروط بر اینکه همه‌ی آن‌ها نیز این پرچم را هنگام ایجاد تنظیم کرده باشند. این گزینه در ویندوز پشتیبانی نمی‌شود.

  • با تنظیم keep_alive روی True، اتصال‌ها با فعال‌سازی ارسال دوره‌ای پیام‌ها فعال نگه داشته می‌شوند.

تغییر یافته در نسخه‌ی 3.13: پارامتر keep_alive اضافه شد.

  • ssl_handshake_timeout (برای یک سرور TLS) مدت‌زمان انتظار به ثانیه برای کامل‌شدن دست‌دهی TLS پیش از قطع اتصال است. اگر None (پیش‌فرض) باشد، 60.0 ثانیه است.

  • ssl_shutdown_timeout زمان انتظار بر حسب ثانیه برای کامل شدن خاموشی SSL (SSL shutdown) پیش از قطع اتصال است. اگر None (پیش‌فرض) باشد، 30.0 ثانیه است.

  • تنظیم start_serving روی True (پیش‌فرض) باعث می‌شود سرور ایجادشده بلافاصله پذیرش اتصال‌ها را آغاز کند. هنگامی که روی False تنظیم شود، کاربر باید Server.start_serving() یا Server.serve_forever() را await کند تا سرور پذیرش اتصال‌ها را آغاز کند.

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از SSL/TLS در ProactorEventLoop افزوده شد.

تغییر یافته در نسخه‌ی 3.5.1: پارامتر host می‌تواند دنباله‌ای از رشته‌ها باشد.

تغییر یافته در نسخه‌ی 3.6: پارامترهای ssl_handshake_timeout و start_serving افزوده شدند. گزینه‌ی سوکت socket.TCP_NODELAY به‌طور پیش‌فرض برای تمام اتصالات TCP تنظیم می‌شود.

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

همچنین ملاحظه نمائید

تابع start_server() یک API جایگزین سطح بالاتر است که یک جفت StreamReader و StreamWriter را برمی‌گرداند و می‌توان از آن‌ها در کد ناهمگام/await استفاده کرد.

async loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)

مشابه loop.create_server() است اما با خانواده‌ی سوکت AF_UNIX کار می‌کند.

path نام یک سوکت دامنه Unix است و لازم است، مگر اینکه آرگومان sock ارائه شده باشد. سوکت‌های انتزاعی Unix، مسیرهای str، bytes و Path پشتیبانی می‌شوند.

اگر cleanup_socket درست باشد، سوکت یونیکس به‌صورت خودکار هنگام بسته شدن سرور از سامانه فایل‌بندی حذف می‌شود، مگر اینکه سوکت پس از ایجاد سرور جایگزین شده باشد.

برای اطلاعات درباره آرگومان‌های این متد، مستندات متد loop.create_server() را ببینید.

تغییر یافته در نسخه‌ی 3.7: پارامترهای ssl_handshake_timeout و start_serving افزوده شدند. پارامتر path اکنون می‌تواند یک شیء Path باشد.

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

تغییر یافته در نسخه‌ی 3.13: پارامتر cleanup_socket افزوده شد.

async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

یک اتصال از پیش پذیرفته‌شده را در یک جفت انتقال/پروتکل قرار دهید.

این متد برای سرورهایی قابل استفاده است که اتصال‌ها را خارج از asyncio می‌پذیرند، اما برای مدیریت آن‌ها از asyncio استفاده می‌کنند.

پارامترها:

  • protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی پروتکل را برمی‌گرداند.

  • sock یک شیء سوکت از پیش موجود است که از socket.accept برگردانده‌شده است.

    توجه

    آرگومان sock مالکیت سوکت را به ترابری ایجادشده منتقل می‌کند. برای بستن سوکت، متد close() همان ترابری را فراخوانی کنید.

  • ssl را می‌توان به یک SSLContext تنظیم کرد تا SSL روی اتصالات پذیرفته‌شده فعال شود.

  • ssl_handshake_timeout (برای یک اتصال SSL) زمان انتظار به ثانیه برای تکمیل دست‌دهی SSL (SSL handshake) پیش از قطع اتصال است. اگر None باشد (پیش‌فرض)، 60.0 ثانیه است.

  • ssl_shutdown_timeout زمان انتظار بر حسب ثانیه برای کامل شدن خاموشی SSL (SSL shutdown) پیش از قطع اتصال است. اگر None (پیش‌فرض) باشد، 30.0 ثانیه است.

یک جفت (transport, protocol) برمی‌گرداند.

اضافه شده در نسخه‌ی 3.5.3.

تغییر یافته در نسخه‌ی 3.7: پارامتر ssl_handshake_timeout اضافه شد.

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

انتقال پرونده‌ها

async loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)

یک پرونده را بر بستر یک انتقال ارسال می‌کند. تعداد کل بایت‌های ارسال‌شده را برمی‌گرداند.

این متد در صورت موجود بودن، از os.sendfile() با کارایی بالا استفاده می‌کند.

file باید یک شیء پرونده معمولی باشد که در حالت دودویی باز شده باشد.

offset مشخص می‌کند که خواندن پرونده از کجا آغاز شود. اگر مشخص شود، count تعداد کل بایت‌هایی است که باید ارسال شوند، به‌جای ارسال پرونده تا رسیدن به EOF. موقعیت پرونده همواره به‌روزرسانی می‌شود، حتی هنگامی که این متد خطایی را پرتاب می‌کند، و می‌توان از file.tell() برای به دست آوردن تعداد واقعی بایت‌های ارسال‌شده استفاده کرد.

تنظیم fallback روی True باعث می‌شود asyncio زمانی که پلتفرم از فراخوانی سیستمی sendfile پشتیبانی نمی‌کند (مثلاً Windows یا سوکت SSL در Unix)، پرونده را به‌صورت دستی بخواند و ارسال کند.

اگر سیستم از فراخوانی سیستمی sendfile پشتیبانی نکند و fallback برابر False باشد، SendfileNotAvailableError پرتاب می‌شود.

اضافه شده در نسخه‌ی 3.7.

ارتقاء TLS

async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)

یک اتصال مبتنی بر ترابری موجود را به TLS ارتقا دهید.

یک نمونه از کدگذار/کدگشای TLS ایجاد کنید و آن را میان انتقال و پروتکل قرار دهید. کدگذار/کدگشا هم پروتکل مواجه با انتقال و هم انتقال مواجه با پروتکل را پیاده‌سازی می‌کند.

نمونه‌ی دو-رابطی ایجادشده را برمی‌گرداند. پس از await، protocol باید استفاده از transport اصلی را متوقف کند و فقط با شیء برگردانده‌شده ارتباط برقرار کند، زیرا کدکننده داده‌های سمت protocol را در نهانگاه ذخیره می‌کند و به‌صورت پراکنده بسته‌های اضافی نشست TLS را با transport مبادله می‌کند.

در برخی شرایط (مثلاً وقتی انتقال ارسال‌شده از قبل در حال بسته‌شدن است) ممکن است این None را برگرداند.

پارامترها:

  • نمونه‌های transport و protocol که متدهایی مانند create_server() و create_connection() برمی‌گردانند.

  • sslcontext: یک نمونه پیکربندی‌شده از SSLContext.

  • server_side هنگامی که یک اتصال سمت سرور در حال ارتقا است، True را ارسال کنید (مانند اتصالی که توسط create_server() ایجاد می‌شود).

  • server_hostname: نام میزبانی را که گواهی سرور هدف با آن تطبیق داده خواهد شد، تنظیم یا بازنویسی می‌کند.

  • ssl_handshake_timeout (برای یک اتصال TLS) مدت‌زمانی به ثانیه است که باید پیش از لغو اتصال، برای تکمیل دست‌دهی TLS (TLS handshake) منتظر ماند. در صورت None بودن، 60.0 ثانیه است (پیش‌فرض).

  • ssl_shutdown_timeout زمان انتظار بر حسب ثانیه برای کامل شدن خاموشی SSL (SSL shutdown) پیش از قطع اتصال است. اگر None (پیش‌فرض) باشد، 30.0 ثانیه است.

اضافه شده در نسخه‌ی 3.7.

تغییر یافته در نسخه‌ی 3.11: پارامتر ssl_shutdown_timeout اضافه شد.

پایش توصیف‌گرهای پرونده

loop.add_reader(fd, callback, *args)

پایش توصیف‌گر پرونده fd را برای دسترس‌پذیری جهت خواندن آغاز کنید و هنگامی که fd برای خواندن در دسترس شد، callback را با آرگومان‌های مشخص‌شده فراخوانی کنید.

هر کال‌بک از پیش ثبت‌شده برای fd لغو می‌شود و با callback جایگزین می‌شود.

loop.remove_reader(fd)

پایش توصیف‌گر پرونده fd را برای دسترس‌پذیری جهت خواندن متوقف می‌کند. اگر fd پیش‌تر برای خواندن پایش می‌شد، True برمی‌گرداند.

loop.add_writer(fd, callback, *args)

پایش توصیف‌گر پرونده fd را برای دسترس‌پذیری جهت نوشتن آغاز کنید و هرگاه fd برای نوشتن در دسترس بود، callback را با آرگومان‌های مشخص‌شده args فراخوانی کنید.

هر کال‌بک از پیش ثبت‌شده برای fd لغو می‌شود و با callback جایگزین می‌شود.

برای ارسال آرگومان‌های کلیدواژه‌ای به کال‌بک از functools.partial() استفاده کنید.

loop.remove_writer(fd)

پایش توصیف‌گر پرونده fd را از نظر دسترس‌پذیری برای نوشتن متوقف می‌کند. اگر fd پیش‌تر برای نوشتن پایش می‌شد، True را برمی‌گرداند.

همچنین برای برخی محدودیت‌های این متدها، بخش Platform Support را ببینید.

کار مستقیم با اشیای سوکت

به‌طور کلی، پیاده‌سازی‌های پروتکلی که از APIهای مبتنی بر انتقال مانند loop.create_connection() و loop.create_server() استفاده می‌کنند، سریع‌تر از پیاده‌سازی‌هایی هستند که به‌طور مستقیم با سوکت‌ها کار می‌کنند. با این حال، برخی موارد استفاده وجود دارند که در آن‌ها عملکرد اهمیت حیاتی ندارد و کار مستقیم با اشیای socket راحت‌تر است.

async loop.sock_recv(sock, nbytes)

حداکثر nbytes را از sock دریافت می‌کند. نسخه ناهمگام socket.recv() است.

داده‌های دریافت‌شده را به‌عنوان یک شیء bytes برگردانید.

sock باید سوکتی غیرمسدود باشد.

تغییر یافته در نسخه‌ی 3.7: اگرچه این متد همیشه به‌عنوان یک متد هم‌روال مستند شده بود، نسخه‌های پیش از پایتون 3.7 یک Future برمی‌گرداندند. از پایتون 3.7، این یک متد async def است.

async loop.sock_recv_into(sock, buf)

داده‌ها را از sock به بافر buf دریافت می‌کند. بر اساس متد مسدودکننده‌ی socket.recv_into() طراحی شده است.

تعداد بایت‌های نوشته‌شده در بافر را برمی‌گرداند.

sock باید سوکتی غیرمسدود باشد.

اضافه شده در نسخه‌ی 3.7.

async loop.sock_recvfrom(sock, bufsize)

یک دیتاگرام با حداکثر اندازه‌ی bufsize را از sock دریافت کنید. نسخه‌ی ناهمگام از socket.recvfrom().

تاپلی از (داده دریافتی، نشانی دوردست) برمی‌گرداند.

sock باید سوکتی غیرمسدود باشد.

اضافه شده در نسخه‌ی 3.11.

async loop.sock_recvfrom_into(sock, buf, nbytes=0)

یک دیتاگرام تا حداکثر nbytes را از sock در buf دریافت کنید. نسخه‌ی ناهمگام socket.recvfrom_into() است.

یک تاپل شامل (تعداد بایت‌های دریافت‌شده، نشانی دوردست) برمی‌گرداند.

sock باید سوکتی غیرمسدود باشد.

اضافه شده در نسخه‌ی 3.11.

async loop.sock_sendall(sock, data)

data را به سوکت sock ارسال می‌کند. نسخه‌ی ناهمگام socket.sendall().

این متد ارسال به سوکت را تا زمانی ادامه می‌دهد که یا تمام داده‌های موجود در data ارسال شده باشد یا خطایی رخ دهد. در صورت موفقیت، None برگردانده می‌شود. در صورت بروز خطا، یک استثنا پرتاب می‌شود. علاوه بر این، راهی برای تعیین اینکه چه مقدار داده، در صورت وجود، در سمت دریابندهی اتصال با موفقیت پردازش شده است، وجود ندارد.

sock باید سوکتی غیرمسدود باشد.

تغییر یافته در نسخه‌ی 3.7: با وجود اینکه این متد همیشه به‌عنوان یک متد هم‌روال مستند شده بود، پیش از پایتون 3.7 یک Future را برمی‌گرداند. از پایتون 3.7، این یک متد async def است.

async loop.sock_sendto(sock, data, address)

یک دیتاگرام را از sock به address ارسال می‌کند. نسخه‌ی ناهمگام socket.sendto().

تعداد بایت‌های ارسال‌شده را برمی‌گرداند.

sock باید سوکتی غیرمسدود باشد.

اضافه شده در نسخه‌ی 3.11.

async loop.sock_connect(sock, address)

sock را به یک سوکت راه دور در address متصل می‌کند.

نسخه‌ی ناهمگام socket.connect().

sock باید سوکتی غیرمسدود باشد.

در SelectorEventLoop، نیازی نیست address ترجمه (resolve) شود: برای سوکت‌های AF_INET و AF_INET6، sock_connect ابتدا با فراخوانی socket.inet_pton() بررسی می‌کند که آیا address از پیش حل شده است یا خیر، و اگر ترجمه‌شده نباشد، برای ترجمه‌ی آن از loop.getaddrinfo() استفاده می‌کند.

ProactorEventLoop، حلقه رویداد پیش‌فرض در ویندوز، نشانی را حل نمی‌کند. میزبان باید از پیش یک نشانی IP عددی باشد؛ ارسال نام میزبان باعث پرتاب OSError می‌شود. ابتدا نشانی را با loop.getaddrinfo() حل کنید، یا از loop.create_connection() استفاده کنید، که نشانی را در همه پلتفرم‌ها حل می‌کند.

تغییر یافته در نسخه‌ی 3.5.2: با SelectorEventLoop، دیگر نیازی به تعیین (resolve) address نیست.

همچنین ملاحظه نمائید

loop.create_connection() و asyncio.open_connection().

async loop.sock_accept(sock)

یک اتصال را می‌پذیرد. بر اساس متد مسدودکننده‌ی socket.accept() مدل‌سازی شده است.

سوکت باید به یک نشانی مقید شده باشد و در حال گوش دادن به اتصال‌ها باشد. مقدار بازگشتی یک جفت (conn, address) است که در آن conn یک شیء سوکت جدید قابل استفاده برای ارسال و دریافت داده روی اتصال است، و address نشانی است که به سوکت در طرف دیگر اتصال مقید شده است.

sock باید سوکتی غیرمسدود باشد.

تغییر یافته در نسخه‌ی 3.7: با وجود اینکه این متد همیشه به‌عنوان یک متد هم‌روال مستند شده بود، پیش از پایتون 3.7 یک Future را برمی‌گرداند. از پایتون 3.7، این یک متد async def است.

همچنین ملاحظه نمائید

loop.create_server() و start_server().

async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)

در صورت امکان، یک پرونده را با استفاده از os.sendfile با کارایی بالا ارسال می‌کند. تعداد کل بایت‌های ارسال‌شده را برمی‌گرداند.

نسخه‌ی ناهمگام از socket.sendfile().

sock باید یک socket غیرمسدود از نوع socket.SOCK_STREAM باشد.

file باید یک شیء پرونده معمولی باشد که در حالت دودویی باز شده است.

offset مشخص می‌کند که خواندن پرونده از کجا آغاز شود. اگر مشخص شود، count تعداد کل بایت‌هایی است که باید ارسال شوند، به‌جای ارسال پرونده تا رسیدن به EOF. موقعیت پرونده همواره به‌روزرسانی می‌شود، حتی هنگامی که این متد خطایی را پرتاب می‌کند، و می‌توان از file.tell() برای به دست آوردن تعداد واقعی بایت‌های ارسال‌شده استفاده کرد.

fallback، وقتی روی True تنظیم شود، باعث می‌شود asyncio زمانی که سکو از فراخوانی سیستمی sendfile پشتیبانی نمی‌کند (مثلاً Windows یا سوکت SSL در Unix)، پرونده را به‌صورت دستی بخواند و ارسال کند.

اگر سیستم از فراخوانی سیستمی sendfile پشتیبانی نکند و fallback برابر False باشد، SendfileNotAvailableError پرتاب می‌شود.

sock باید سوکتی غیرمسدود باشد.

اضافه شده در نسخه‌ی 3.7.

DNS

async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)

نسخه‌ی ناهمگام socket.getaddrinfo().

async loop.getnameinfo(sockaddr, flags=0)

نسخه‌ی ناهمگام socket.getnameinfo().

توجه

هر دو getaddrinfo و getnameinfo به‌صورت داخلی از نسخه‌های همگام خود از طریق اجراکننده‌ی استخر نخ پیش‌فرض حلقه (thread pool executor) استفاده می‌کنند. هنگامی که این اجراکننده اشباع شود، این متدها ممکن است با تأخیر مواجه شوند؛ کتابخانه‌های شبکه‌ای سطح بالاتر ممکن است این تأخیرها را به‌صورت افزایش مهلت زمانی گزارش کنند. برای کاهش این مشکل، استفاده از یک اجراکننده‌ی سفارشی برای سایر وظایف کاربر، یا تنظیم یک اجراکننده‌ی پیش‌فرض با تعداد بیشتری کارگر را در نظر بگیرید.

تغییر یافته در نسخه‌ی 3.7: در مستندات همواره آمده بود که هر دو متد getaddrinfo و getnameinfo یک هم‌روال برمی‌گردانند، اما پیش از Python 3.7، آن‌ها در واقع اشیای asyncio.Future را برمی‌گرداندند. از Python 3.7 به بعد، هر دو متد هم‌روال هستند.

کار با پایپ‌ها

async loop.connect_read_pipe(protocol_factory, pipe)

انتهای خواندن pipe را در حلقه رویداد ثبت کنید.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی از پروتکل asyncio را برمی‌گرداند.

pipe یک شیء شبه‌پرونده است. برای مشاهده‌ی اشیاء پشتیبانی‌شده به‌عنوان pipe، اشیای pipe پشتیبانی‌شده را ببینید.

یک جفت (transport, protocol) را برمی‌گرداند، که در آن transport از رابط ReadTransport پشتیبانی می‌کند و protocol شیءای است که protocol_factory آن را نمونه‌سازی کرده است.

در حلقه رویداد SelectorEventLoop، پایپ به حالت غیرمسدودکننده تنظیم می‌شود.

async loop.connect_write_pipe(protocol_factory, pipe)

انتهای نوشتن pipe را در حلقه رویداد ثبت کنید.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که یک پیاده‌سازی از پروتکل asyncio را برمی‌گرداند.

pipe یک شیء شبه‌پرونده است. برای مشاهده‌ی اشیاء پشتیبانی‌شده به‌عنوان pipe، اشیای pipe پشتیبانی‌شده را ببینید.

یک جفت (transport, protocol) را برمی‌گرداند، که در آن transport از رابط WriteTransport پشتیبانی می‌کند و protocol یک شیء نمونه‌سازی‌شده توسط protocol_factory است.

در حلقه رویداد SelectorEventLoop، پایپ به حالت غیرمسدودکننده تنظیم می‌شود.

اشیای pipe پشتیبانی‌شده

این متدها فقط با اشیایی کار می‌کنند که سیستم‌عامل بتواند آمادگی آن‌ها را پایش کند یا روی آن‌ها ورودی/خروجی همپوشانی‌شده (overlapped I/O) انجام دهد. از پرونده‌های معمولی روی دیسک در هیچ پلتفرمی پشتیبانی نمی‌شود. هیچ ورودی/خروجی ناهمگام پرونده‌ای در asyncio وجود ندارد؛ برای خواندن و نوشتن پرونده‌های معمولی بدون مسدود کردن حلقه رویداد، از loop.run_in_executor() استفاده کنید.

در یونیکس، با SelectorEventLoop، pipe باید پوششی برای یکی از موارد زیر باشد:

  • یک پایپ، مانند یکی از سرهای یک جفت os.pipe() یا یک FIFO ایجادشده با os.mkfifo()؛

  • یک سوکت؛

  • یک دستگاه نویسه‌ای، مانند یک پایانه.

در ویندوز، که تنها ProactorEventLoop این متدها را پیاده‌سازی می‌کند، pipe باید یک دسته را که برای I/O همپوشانی‌شده (overlapped I/O) باز شده است (یعنی با پرچم FILE_FLAG_OVERLAPPED ایجاد شده است)، دربرگیرد، زیرا دسته باید به یک پورت تکمیل I/O (I/O completion port) مرتبط باشد. دسته‌هایی که برای I/O همپوشانی‌شده باز نشده‌اند، رد می‌شوند. به‌ویژه، جریان‌های استاندارد (sys.stdin، sys.stdout و sys.stderr)، دسته‌های کنسول و پایپ‌های ایجادشده توسط os.pipe() برای I/O همپوشانی‌شده باز نشده‌اند و بنابراین نمی‌توان از آن‌ها با این متدها استفاده کرد.

توجه

SelectorEventLoop از متدهای بالا در ویندوز پشتیبانی نمی‌کند. در ویندوز، به‌جای آن از ProactorEventLoop استفاده کنید.

همچنین ملاحظه نمائید

متدهای loop.subprocess_exec() و loop.subprocess_shell().

سیگنال‌های یونیکس

loop.add_signal_handler(signum, callback, *args)

callback را به‌عنوان هندلر سیگنال signum تنظیم کنید و args را به‌عنوان آرگومان‌های جایگاهی ارسال کنید.

کال‌بک توسط loop، همراه با سایر کال‌بک‌های در صف و هم‌روال‌های قابل اجرا در آن حلقه رویداد، فراخوانی می‌شود. برخلاف هندلرهای سیگنال ثبت‌شده با استفاده از signal.signal()، کال‌بک ثبت‌شده با این تابع مجاز است با حلقه رویداد تعامل داشته باشد.

اگر شماره سیگنال نامعتبر یا غیرقابل‌دریافت باشد، ValueError پرتاب می‌شود. اگر در راه‌اندازی هندلر مشکلی وجود داشته باشد، RuntimeError پرتاب می‌شود.

برای ارسال آرگومان‌های کلیدواژه‌ای به کال‌بک از functools.partial() استفاده کنید.

مانند signal.signal()، این تابع باید در نخ اصلی فراخوانی شود.

loop.remove_signal_handler(sig)

هندلر سیگنال sig را حذف کنید.

اگر هندلر سیگنال حذف شده باشد، True را برمی‌گرداند، یا اگر برای سیگنال داده‌شده هیچ هندلری تنظیم نشده باشد، False را برمی‌گرداند.

همچنین ملاحظه نمائید

ماژول signal.

اجرای کد در استخرهای نخ یا فرایند

awaitable loop.run_in_executor(executor, func, *args)

ترتیبی دهید که func در اجراکننده‌ی مشخص‌شده (executor) با ارسال args به‌عنوان آرگومان‌های جایگاهی فراخوانی شود.

آرگومان executor باید نمونه‌ای از concurrent.futures.Executor باشد. اگر executor برابر None باشد، از اجراکننده پیش‌فرض استفاده می‌شود. اجراکننده پیش‌فرض را می‌توان با loop.set_default_executor() تنظیم کرد؛ در غیر این صورت، یک concurrent.futures.ThreadPoolExecutor به‌صورت تنبل مقداردهی اولیه می‌شود و run_in_executor() در صورت نیاز از آن استفاده می‌کند.

مثال:

import asyncio
import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

    ## Options:

    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, blocking_io)
    print('default thread pool', result)

    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom process pool', result)

    # 4. Run in a custom interpreter pool:
    with concurrent.futures.InterpreterPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, cpu_bound)
        print('custom interpreter pool', result)

if __name__ == '__main__':
    asyncio.run(main())

توجه داشته باشید که نگهبان نقطه ورود (if __name__ == '__main__') به دلیل ویژگی‌های خاص multiprocessing، که توسط ProcessPoolExecutor استفاده می‌شود، برای گزینه‌ی ۳ لازم است. ایمپورت امن ماژول اصلی را ببینید.

این متد یک شیء asyncio.Future را برمی‌گرداند.

برای فرستادن آرگومان‌های کلیدواژه‌ای به func از functools.partial() استفاده کنید.

تغییر یافته در نسخه‌ی 3.5.3: loop.run_in_executor() دیگر max_workers اجراکننده‌ی استخر نخی را که ایجاد می‌کند، پیکربندی نمی‌کند، بلکه تعیین مقدار پیش‌فرض را به خود اجراکننده‌ی استخر نخ (ThreadPoolExecutor) واگذار می‌کند.

loop.set_default_executor(executor)

executor را به‌عنوان اجراکننده پیش‌فرضی که توسط run_in_executor() استفاده می‌شود، تنظیم کنید. executor باید نمونه‌ای از ThreadPoolExecutor باشد، که InterpreterPoolExecutor را نیز شامل می‌شود.

تغییر یافته در نسخه‌ی 3.11: executor باید نمونه‌ای از ThreadPoolExecutor باشد.

API مدیریت خطا

امکان سفارشی‌سازی چگونگی مدیریت استثناها در حلقه‌ی رویداد را فراهم می‌کند.

loop.set_exception_handler(handler)

handler را به‌عنوان هندلر استثنای جدید حلقه‌ی رویداد تنظیم کنید.

اگر handler برابر None باشد، هندلر پیش‌فرض استثنا تنظیم خواهد شد. در غیر این صورت، handler باید یک شیء فراخوانی‌پذیر با امضایی مطابق با (loop, context) باشد، که loop ارجاعی به حلقه‌ی رویداد فعال است و context یک شیء dict حاوی جزئیات استثنا است (برای جزئیات درباره‌ی context، مستندات call_exception_handler() را ببینید).

اگر هندلر از طرف یک Task یا Handle فراخوانی شود، در contextvars.Context آن Task یا دسته کال‌بک (callback handle) اجرا می‌شود.

تغییر یافته در نسخه‌ی 3.12: ممکن است هندلر در Context مربوط به تکلیف یا دسته‌ای که استثنا از آن منشأ گرفته است، فراخوانی شود.

loop.get_exception_handler()

هندلر استثنای فعلی را برمی‌گرداند، یا اگر هیچ هندلر استثنای سفارشی تنظیم نشده باشد None را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.5.2.

loop.default_exception_handler(context)

هندلر استثنای پیش‌فرض.

این هنگامی فراخوانی می‌شود که استثنایی رخ دهد و هیچ هندلر استثنایی تنظیم نشده باشد. این می‌تواند توسط یک هندلر استثنای سفارشی که می‌خواهد رفتار را به هندلر پیش‌فرض واگذار کند، فراخوانی شود.

پارامتر context همان معنایی را دارد که در call_exception_handler() آمده است.

loop.call_exception_handler(context)

هندلر استثنای حلقه رویداد جاری را فراخوانی کنید.

context یک شیء dict حاوی کلیدهای زیر است (ممکن است کلیدهای جدیدی در نسخه‌های آینده پایتون افزوده شوند):

  • 'message': پیام خطا؛

  • 'exception' (اختیاری): شیء استثنا؛

  • 'future' (اختیاری): نمونه‌ی asyncio.Future؛

  • 'task' (اختیاری): نمونه‌ی asyncio.Task؛

  • 'handle' (اختیاری): نمونه‌ی asyncio.Handle؛

  • 'protocol' (اختیاری): نمونه‌ی Protocol؛

  • 'transport' (اختیاری): نمونه‌ی Transport؛

  • 'socket' (اختیاری): نمونه‌ی socket.socket؛

  • 'source_traceback' (اختیاری): ردگیری پشته‌ی منبع؛

  • 'handle_traceback' (اختیاری): ردگیری پشته‌ی دسته ؛

  • 'asyncgen' (اختیاری): تولیدگر ناهمگامی که باعث شد

    استثنا.

توجه

این متد نباید در حلقه‌های رویداد زیرکلاس‌شده سربارگذاری (overload) شود. برای مدیریت سفارشی استثنا، از متد set_exception_handler() استفاده کنید.

فعال‌سازی حالت اشکال‌زدایی

loop.get_debug()

حالت اشکال‌زدایی (bool) حلقه رویداد را دریافت می‌کند.

اگر متغیر محیطی PYTHONASYNCIODEBUG به رشته‌ای غیرخالی تنظیم شده باشد، مقدار پیش‌فرض True است؛ در غیر این صورت False است.

loop.set_debug(enabled: bool)

حالت اشکال‌زدایی حلقه رویداد را تنظیم کنید.

تغییر یافته در نسخه‌ی 3.7: اکنون می‌توان از حالت توسعه پایتون جدید نیز برای فعال‌سازی حالت اشکال‌زدایی استفاده کرد.

loop.slow_callback_duration

از این ویژگی می‌توان برای تنظیم حداقل مدت زمان اجرا بر حسب ثانیه که «کند» در نظر گرفته می‌شود، استفاده کرد. هنگامی که حالت اشکال‌زدایی فعال باشد، کال‌بک‌های «کند» ثبت می‌شوند.

مقدار پیش‌فرض ۱۰۰ میلی‌ثانیه است.

همچنین ملاحظه نمائید

حالت اشکال‌زدایی asyncio.

اجرای زیرفرایندها

متدهای توصیف‌شده در این زیربخش سطح پایین هستند. در کد معمول ناهمگام/await، بهتر است به‌جای آن‌ها از توابع کمکی سطح بالای asyncio.create_subprocess_shell() و asyncio.create_subprocess_exec() استفاده کنید.

توجه

در ویندوز، حلقه رویداد پیش‌فرض ProactorEventLoop از زیرفرایندها پشتیبانی می‌کند، در حالی که SelectorEventLoop پشتیبانی نمی‌کند. برای جزئیات، پشتیبانی از زیرفرایند در ویندوز را ببینید.

async loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

یک زیرفرایند از یک یا چند آرگومان رشته‌ای مشخص‌شده توسط args ایجاد می‌کند.

args باید فهرستی از رشته‌ها باشد که به‌صورت زیر نمایش داده می‌شود:

اولین رشته، پرونده اجرایی برنامه را مشخص می‌کند و رشته‌های باقی‌مانده آرگومان‌ها را مشخص می‌کنند. آرگومان‌های رشته‌ای با هم، argv برنامه را تشکیل می‌دهند.

این مشابه کلاس subprocess.Popen در کتابخانه‌ی استاندارد است که با shell=False و فهرستی از رشته‌ها به‌عنوان اولین آرگومان فراخوانی می‌شود؛ با این حال، در حالی که Popen یک آرگومان واحد می‌گیرد که فهرستی از رشته‌ها است، subprocess_exec چندین آرگومان رشته‌ای می‌گیرد.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که زیرکلاسی از کلاس asyncio.SubprocessProtocol را برمی‌گرداند.

پارامترهای دیگر:

  • stdin می‌تواند هر یک از این موارد باشد:

    • یک شیء شبه‌پرونده

    • یک توصیف‌گر پرونده موجود (یک عدد صحیح مثبت)، برای مثال مواردی که با os.pipe() ایجاد شده‌اند.

    • ثابت subprocess.PIPE (پیش‌فرض) که یک پایپ جدید ایجاد کرده و آن را متصل می‌کند،

    • مقدار None که باعث می‌شود زیرفرایند توصیف‌گر پرونده را از این فرایند به ارث ببرد

    • ثابت subprocess.DEVNULL که نشان می‌دهد پرونده ویژه‌ی os.devnull استفاده خواهد شد

  • stdout می‌تواند هر یک از موارد زیر باشد:

    • یک شیء شبه‌پرونده

    • ثابت subprocess.PIPE (پیش‌فرض) که یک پایپ جدید ایجاد کرده و آن را متصل می‌کند،

    • مقدار None که باعث می‌شود زیرفرایند توصیف‌گر پرونده را از این فرایند به ارث ببرد

    • ثابت subprocess.DEVNULL که نشان می‌دهد پرونده ویژه‌ی os.devnull استفاده خواهد شد

  • stderr می‌تواند هر یک از این موارد باشد:

    • یک شیء شبه‌پرونده

    • ثابت subprocess.PIPE (پیش‌فرض) که یک پایپ جدید ایجاد کرده و آن را متصل می‌کند،

    • مقدار None که باعث می‌شود زیرفرایند توصیف‌گر پرونده را از این فرایند به ارث ببرد

    • ثابت subprocess.DEVNULL که نشان می‌دهد پرونده ویژه‌ی os.devnull استفاده خواهد شد

    • ثابت subprocess.STDOUT که جریان خطای استاندارد را به جریان خروجی استاندارد فرایند متصل می‌کند

  • تمام آرگومان‌های کلیدواژه‌ای دیگر بدون تفسیر به subprocess.Popen منتقل می‌شوند، به جز bufsize، universal_newlines، shell، text، encoding و errors، که نباید به هیچ وجه تعیین شوند.

    API زیرفرایند asyncio از کدگشایی جریان‌ها به‌صورت متن پشتیبانی نمی‌کند. می‌توان از bytes.decode() برای تبدیل بایت‌های برگردانده‌شده از جریان به متن استفاده کرد.

اگر یک شیء شبه‌پرونده که به‌عنوان stdin، stdout یا stderr ارسال شده است، نمایانگر یک پایپ باشد، طرف دیگر این پایپ باید با connect_write_pipe() یا connect_read_pipe() برای استفاده با حلقه رویداد ثبت شود.

برای مستندات مربوط به سایر آرگومان‌ها، سازنده‌ی کلاس subprocess.Popen را ببینید.

یک جفت (transport, protocol) برمی‌گرداند، که در آن transport با کلاس پایه asyncio.SubprocessTransport مطابقت دارد و protocol شیء‌ای است که توسط protocol_factory نمونه‌سازی شده است.

اگر انتقال بسته یا زباله‌روبی شود، فرایند فرزند در صورتی که هنوز در حال اجرا باشد، کشته می‌شود.

async loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)

با استفاده از سینتکس پوسته‌ی سکو، یک زیرفرایند از cmd، که می‌تواند یک رشته‌ی str یا یک رشته‌ی bytes کدگذاری‌شده با کدگذاری سامانه فایل‌بندی باشد، ایجاد کنید.

این مشابه کلاس subprocess.Popen در کتابخانه استاندارد است که با shell=True فراخوانی می‌شود.

protocol_factory باید یک شیء فراخوانی‌پذیر باشد که زیرکلاسی از کلاس SubprocessProtocol را برمی‌گرداند.

برای جزئیات بیشتر درباره آرگومان‌های باقی‌مانده، subprocess_exec() را ببینید.

یک جفت (transport, protocol) برمی‌گرداند، که در آن transport با کلاس پایه SubprocessTransport مطابقت دارد و protocol شیء‌ای است که توسط protocol_factory نمونه‌سازی شده است.

اگر انتقال بسته یا زباله‌روبی شود، فرایند فرزند در صورتی که هنوز در حال اجرا باشد، کشته می‌شود.

توجه

بر عهده‌ی برنامه است که اطمینان حاصل کند همه‌ی نویسه‌های فضای خالی و نویسه‌های خاص به‌درستی داخل علامت نقل‌قول قرار گرفته باشند تا از آسیب‌پذیری‌های تزریق پوسته (shell injection) جلوگیری شود. می‌توان از تابع shlex.quote() برای خنثی کردن صحیح نویسه‌های فضای خالی و نویسه‌های خاص در رشته‌هایی که قرار است برای ساخت دستورات پوسته استفاده شوند، استفاده کرد.

دسته‌های کال‌بک

class asyncio.Handle

یک شیء پوششی کال‌بک که توسط loop.call_soon() و loop.call_soon_threadsafe() برگردانده می‌شود.

get_context()

شیء contextvars.Context مرتبط با دسته را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.12.

cancel()

کال‌بک را لغو می‌کند. اگر کال‌بک پیش‌تر لغو یا اجرا شده باشد، این متد هیچ اثری ندارد.

cancelled()

اگر کال‌بک لغو شده باشد، True برمی‌گرداند.

اضافه شده در نسخه‌ی 3.7.

class asyncio.TimerHandle

یک شیء پوششی کال‌بک که توسط loop.call_later() و loop.call_at() بازگردانده می‌شود.

این کلاس زیرکلاسی از Handle است.

when()

زمان یک کال‌بک زمان‌بندی‌شده را به‌صورت float بر حسب ثانیه برمی‌گرداند.

زمان یک برچسب زمانی مطلق است که از همان مرجع زمان loop.time() استفاده می‌کند.

اضافه شده در نسخه‌ی 3.7.

اشیای سرور

اشیای سرور توسط توابع loop.create_server()، loop.create_unix_server()، start_server() و start_unix_server() ایجاد می‌شوند.

کلاس Server را مستقیماً نمونه‌سازی نکنید.

class asyncio.Server

اشیای Server مدیرهای زمینه ناهمگام هستند. هنگامی که در یک دستور async with استفاده شوند، تضمین می‌شود که شیء Server در زمان کامل شدن دستور async with بسته است و اتصال‌های جدید را نمی‌پذیرد:

srv = await loop.create_server(...)

async with srv:
    # some code

# At this point, srv is closed and no longer accepts new connections.

تغییر یافته در نسخه‌ی 3.7: شیء Server از پایتون 3.7، یک مدیر زمینه ناهمگام است.

تغییر یافته در نسخه‌ی 3.11: این کلاس در پایتون 3.9.11، 3.10.3 و 3.11 به‌صورت عمومی با عنوان asyncio.Server در دسترس قرار گرفت.

close()

توقف سرویس‌دهی: سوکت‌های شنونده را ببندید و ویژگی sockets را روی None قرار دهید.

سوکت‌هایی که نشان‌دهنده‌ی اتصالات ورودی موجودِ کلاینت‌ها هستند، باز می‌مانند.

سرور به‌صورت ناهمگام بسته می‌شود؛ از هم‌روال wait_closed() برای صبر کردن تا زمانی که سرور بسته شود (و دیگر هیچ اتصالی فعال نباشد) استفاده کنید.

close_clients()

تمام اتصالات ورودی موجود کلاینت را ببندید.

close() را برای تمام انتقال‌های مرتبط فراخوانی می‌کند.

هنگام بستن سرور، برای جلوگیری از رقابت با اتصال کلاینت‌های جدید، باید close() را پیش از close_clients() فراخوانی کرد.

اضافه شده در نسخه‌ی 3.13.

abort_clients()

تمام اتصال‌های ورودی کلاینت موجود را بلافاصله ببندید، بدون انتظار برای تکمیل عملیات‌های در انتظار.

abort() را روی تمام انتقال‌های مرتبط فراخوانی می‌کند.

هنگام بستن سرور، باید close() پیش از abort_clients() فراخوانی شود تا از رقابت با کلاینت‌های جدیدی که در حال اتصال هستند اجتناب شود.

اضافه شده در نسخه‌ی 3.13.

get_loop()

حلقه رویداد مرتبط با شیء سرور را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.7.

async start_serving()

پذیرش اتصال‌ها را آغاز کنید.

این متد هم‌توان (idempotent) است، بنابراین می‌توان آن را هنگامی که سرور از قبل در حال سرویس‌دهی است فراخوانی کرد.

پارامتر فقط کلیدواژه‌ای start_serving در loop.create_server() و asyncio.start_server() امکان ایجاد یک شیء Server را فراهم می‌کند که در ابتدا اتصال‌ها را نمی‌پذیرد. در این حالت، می‌توان از Server.start_serving() یا Server.serve_forever() برای شروع پذیرش اتصال‌ها توسط Server استفاده کرد.

اضافه شده در نسخه‌ی 3.7.

async serve_forever()

پذیرش اتصال‌ها را تا زمانی که هم‌روال لغو شود، آغاز می‌کند. لغو وظیفه serve_forever باعث بسته شدن سرور می‌شود.

این متد را می‌توان در صورتی فراخوانی کرد که سرور از قبل در حال پذیرش اتصال‌ها باشد. به ازای هر شیء Server، تنها یک وظیفه serve_forever می‌تواند وجود داشته باشد.

مثال:

async def client_connected(reader, writer):
    # Communicate with the client with
    # reader/writer streams.  For example:
    await reader.readline()

async def main(host, port):
    srv = await asyncio.start_server(
        client_connected, host, port)
    await srv.serve_forever()

asyncio.run(main('127.0.0.1', 0))

اضافه شده در نسخه‌ی 3.7.

is_serving()

اگر سرور در حال پذیرش اتصال‌های جدید باشد، True را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.7.

async wait_closed()

صبر کنید تا متد close() کامل شود و تمام اتصال‌های فعال به پایان رسیده باشند.

تغییر یافته در نسخه‌ی 3.12: wait_closed() اکنون صبر می‌کند تا سرور بسته شود و تمام اتصال‌های فعال به پایان برسند. پیش از این، اگر سرور از قبل بسته شده بود، حتی اگر اتصال‌ها هنوز فعال بودند، بلافاصله بازمی‌گشت.

sockets

فهرستی از اشیاء شبه‌سوکت، asyncio.trsock.TransportSocket، که سرور به آن‌ها گوش می‌دهد.

تغییر یافته در نسخه‌ی 3.7: پیش از پایتون 3.7، Server.sockets مستقیماً یک فهرست داخلی از سوکت‌های سرور را برمی‌گرداند. در 3.7، یک کپی از آن فهرست برگردانده می‌شود.

پیاده‌سازی‌های حلقه رویداد

asyncio با دو پیاده‌سازی مختلف حلقه رویداد ارائه می‌شود: SelectorEventLoop و ProactorEventLoop.

به‌طور پیش‌فرض، asyncio برای استفاده از EventLoop پیکربندی شده است.

class asyncio.SelectorEventLoop

زیرکلاسی از AbstractEventLoop مبتنی بر ماژول selectors.

از کارآمدترین انتخابگر موجود برای سکوی داده‌شده استفاده می‌کند. همچنین می‌توان پیاده‌سازی دقیق انتخابگر مورد استفاده را به‌صورت دستی پیکربندی کرد:

import asyncio
import selectors

async def main():
   ...

loop_factory = lambda: asyncio.SelectorEventLoop(selectors.SelectSelector())
asyncio.run(main(), loop_factory=loop_factory)

دسترس‌پذیری: Unix, Windows.

class asyncio.ProactorEventLoop

یک زیرکلاس از AbstractEventLoop برای ویندوز که از «I/O Completion Ports» (IOCP) استفاده می‌کند.

class asyncio.EventLoop

نام مستعاری به کارآمدترین زیرکلاسِ در دسترسِ AbstractEventLoop برای سکوی داده‌شده.

این یک نام مستعار برای SelectorEventLoop در یونیکس و ProactorEventLoop در ویندوز است.

اضافه شده در نسخه‌ی 3.13.

class asyncio.AbstractEventLoop

کلاس پایه انتزاعی برای حلقه‌های رویداد سازگار با asyncio.

بخش متدهای حلقه رویداد همه‌ی متدهایی را که یک پیاده‌سازی جایگزین از AbstractEventLoop باید تعریف کرده باشد، فهرست می‌کند.

مثال‌ها

توجه داشته باشید که همه نمونه‌های این بخش عمداً نشان می‌دهند که چگونه از APIهای سطح پایین حلقه رویداد، مانند loop.run_forever() و loop.call_soon()، استفاده کنید. برنامه‌های کاربردی مدرن asyncio به‌ندرت لازم است به این شکل نوشته شوند؛ استفاده از توابع سطح بالا مانند asyncio.run() را در نظر بگیرید.

سلام دنیا با call_soon()

مثالی که از متد loop.call_soon() برای زمان‌بندی یک کال‌بک استفاده می‌کند. این کال‌بک "Hello World" را نمایش می‌دهد و سپس حلقه رویداد را متوقف می‌کند:

import asyncio

def hello_world(loop):
    """A callback to print 'Hello World' and stop the event loop"""
    print('Hello World')
    loop.stop()

loop = asyncio.new_event_loop()

# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

همچنین ملاحظه نمائید

مثالی مشابه سلام دنیا که با یک هم‌روال و تابع run() ایجاد شده است.

نمایش تاریخ فعلی با call_later()

نمونه‌ای از یک کال‌بک که تاریخ جاری را هر ثانیه نمایش می‌دهد. این کال‌بک از متد loop.call_later() برای زمان‌بندی مجدد خود پس از ۵ ثانیه استفاده می‌کند و سپس حلقه رویداد را متوقف می‌کند:

import asyncio
import datetime as dt

def display_date(end_time, loop):
    print(dt.datetime.now())
    if (loop.time() + 1.0) < end_time:
        loop.call_later(1, display_date, end_time, loop)
    else:
        loop.stop()

loop = asyncio.new_event_loop()

# Schedule the first call to display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)

# Blocking call interrupted by loop.stop()
try:
    loop.run_forever()
finally:
    loop.close()

همچنین ملاحظه نمائید

مثالی مشابه از تاریخ جاری که با یک هم‌روال و تابع run() ایجاد شده است.

پایش یک توصیف‌گر پرونده برای رویدادهای خواندن

منتظر بمانید تا یک توصیف‌گر پرونده با استفاده از متد loop.add_reader() داده‌ای دریافت کند و سپس حلقه رویداد را ببندید:

import asyncio
from socket import socketpair

# Create a pair of connected file descriptors
rsock, wsock = socketpair()

loop = asyncio.new_event_loop()

def reader():
    data = rsock.recv(100)
    print("Received:", data.decode())

    # We are done: unregister the file descriptor
    loop.remove_reader(rsock)

    # Stop the event loop
    loop.stop()

# Register the file descriptor for read event
loop.add_reader(rsock, reader)

# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())

try:
    # Run the event loop
    loop.run_forever()
finally:
    # We are done. Close sockets and the event loop.
    rsock.close()
    wsock.close()
    loop.close()

همچنین ملاحظه نمائید

تنظیم هندلرهای سیگنال برای SIGINT و SIGTERM

(این مثال signal فقط در یونیکس کار می‌کند.)

با استفاده از متد loop.add_signal_handler()، هندلرهایی برای سیگنال‌های SIGINT و SIGTERM ثبت کنید:

import asyncio
import functools
import os
import signal

def ask_exit(signame, loop):
    print("got signal %s: exit" % signame)
    loop.stop()

async def main():
    loop = asyncio.get_running_loop()

    for signame in {'SIGINT', 'SIGTERM'}:
        loop.add_signal_handler(
            getattr(signal, signame),
            functools.partial(ask_exit, signame, loop))

    await asyncio.sleep(3600)

print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")

asyncio.run(main())