اجراکنندهها¶
کد منبع: Lib/asyncio/runners.py
این بخش، سازوکارهای اولیه سطح بالای asyncio برای اجرای کد asyncio را بهطور خلاصه شرح میدهد.
آنها بر پایه یک حلقه رویداد ساخته شدهاند تا استفاده از کد ناهمگام را برای سناریوهای رایج و گسترده سادهتر کنند.
اجرای یک برنامه asyncio¶
- asyncio.run(coro, *, debug=None, loop_factory=None)¶
coro را در یک حلقه رویداد asyncio اجرا میکند و نتیجه را برمیگرداند.
آرگومان میتواند هر شیء awaitable باشد.
این تابع، awaitable را اجرا میکند و مدیریت حلقه رویداد asyncio، نهاییسازی تولیدگرهای ناهمگام و بستن اجراکننده (executor) را بر عهده میگیرد.
هنگامی که یک حلقه رویداد asyncio دیگر در همان نخ در حال اجرا است، نمیتوانید این تابع را فراخوانی کنید.
اگر debug برابر
Trueباشد، حلقه رویداد در حالت اشکالزدایی اجرا میشود.Falseحالت اشکالزدایی را بهصراحت غیرفعال میکند.Noneبرای رعایت تنظیمات سراسری حالت اشکالزدایی استفاده میشود.اگر loop_factory
Noneنباشد، از آن برای ایجاد یک حلقه رویداد جدید استفاده میشود؛ در غیر این صورت ازasyncio.new_event_loop()استفاده میشود. حلقه در پایان بسته میشود. این تابع باید به عنوان نقطه ورود اصلی برنامههای asyncio استفاده شود و بهتر است فقط یک بار فراخوانی شود. توصیه میشود به جای سیاستها (policies)، برای پیکربندی حلقه رویداد از loop_factory استفاده کنید. ارسالasyncio.EventLoopامکان اجرای asyncio بدون سیستم سیاست (policy system) را فراهم میکند.به اجراکننده (executor) مهلتی به مدت ۵ دقیقه برای خاموش شدن داده میشود. اگر اجراکننده در آن مدت کار خود را به پایان نرسانده باشد، هشداری نشان داده میشود و اجراکننده بسته میشود.
مثال:
async def main(): await asyncio.sleep(1) print('hello') asyncio.run(main())
اضافه شده در نسخهی 3.7.
تغییر یافته در نسخهی 3.9: برای استفاده از
loop.shutdown_default_executor()بهروزرسانی شد.تغییر یافته در نسخهی 3.10: debug بهطور پیشفرض
Noneاست تا تنظیمات سراسری حالت اشکالزدایی را رعایت کند.تغییر یافته در نسخهی 3.12: پارامتر loop_factory افزوده شد.
تغییر یافته در نسخهی 3.14: coro میتواند هر شیء قابل await (awaitable) باشد.
توجه
سیستم سیاست
asyncioمنسوخ شده است و در Python 3.16 حذف خواهد شد؛ از آن پس، برای پیکربندی حلقه رویداد به یک loop_factory صریح نیاز است.
مدیر زمینهی Runner¶
- class asyncio.Runner(*, debug=None, loop_factory=None)¶
مدیر زمینهای که فراخوانیهای چندگانه تابع ناهمگام را در همان زمینه سادهتر میکند.
گاهی اوقات چندین تابع ناهمگام سطح بالا باید در یک حلقه رویداد و
contextvars.Contextمشترک فراخوانی شوند.اگر debug برابر
Trueباشد، حلقه رویداد در حالت اشکالزدایی اجرا میشود.Falseحالت اشکالزدایی را بهصراحت غیرفعال میکند.Noneبرای رعایت تنظیمات سراسری حالت اشکالزدایی استفاده میشود.loop_factory میتواند برای بازنویسی ایجاد حلقه استفاده شود. مسئولیت تنظیم حلقهی ایجادشده بهعنوان حلقهی جاری بر عهدهی loop_factory است. بهطور پیشفرض، اگر loop_factory برابر
Noneباشد، ازasyncio.new_event_loop()استفاده میشود و باasyncio.set_event_loop()بهعنوان حلقهی رویداد جاری تنظیم میشود.اساساً، میتوان مثال
asyncio.run()را با استفاده از اجراکننده (runner) بازنویسی کرد:async def main(): await asyncio.sleep(1) print('hello') with asyncio.Runner() as runner: runner.run(main())
اضافه شده در نسخهی 3.11.
- run(coro, *, context=None)¶
coro را در حلقه رویداد تعبیهشده اجرا کنید.
آرگومان میتواند هر شیء awaitable باشد.
اگر آرگومان یک همروال باشد، در یک Task پیچیده میشود.
یک آرگومان اختیاری فقط کلیدواژهای context به شما امکان میدهد یک
contextvars.Contextسفارشی برای کدی که در آن اجرا میشود مشخص کنید. اگر context برابرNoneباشد، از زمینه پیشفرض اجراکننده استفاده میشود.نتیجهی awaitable را برمیگرداند یا یک استثنا را پرتاب میکند.
هنگامی که یک حلقه رویداد asyncio دیگر در همان نخ در حال اجرا است، نمیتوانید این تابع را فراخوانی کنید.
تغییر یافته در نسخهی 3.14: coro میتواند هر شیء قابل await (awaitable) باشد.
- close()¶
اجراکننده را ببندید.
نهاییسازی تولیدگرهای ناهمگام، خاموش کردن اجراکنندهی پیشفرض، بستن حلقهی رویداد و آزادسازی
contextvars.Contextتعبیهشده.
- get_loop()¶
حلقهی رویداد مرتبط با نمونهی اجراکننده را بازمیگرداند.
توجه
Runnerاز راهبرد مقداردهی اولیه تنبل استفاده میکند، سازندهی آن ساختارهای زیربنایی سطح پایین را مقداردهی اولیه نمیکند.حلقه و زمینه تعبیهشده در هنگام ورود به بدنهی
withیا نخستین فراخوانیrun()یاget_loop()ایجاد میشوند.
مدیریت وقفه صفحهکلید¶
اضافه شده در نسخهی 3.11.
هنگامی که signal.SIGINT با Ctrl-C پرتاب میشود، بهطور پیشفرض استثنای KeyboardInterrupt در نخ اصلی پرتاب میشود. اما این مورد با asyncio کار نمیکند، زیرا میتواند اجزای داخلی asyncio را مختل کند و باعث شود برنامه هنگام خروج معلق بماند.
برای کاهش این مشکل، asyncio، signal.SIGINT را بهصورت زیر مدیریت میکند:
asyncio.Runner.run()پیش از اجرای هر کد کاربر، یک هندلر سفارشی برایsignal.SIGINTنصب میکند و هنگام خروج از تابع، آن را حذف میکند.Runnerبرای اجرای همروالِ دادهشده، وظیفهی اصلیرا ایجاد میکند.هنگامی که
signal.SIGINTبا Ctrl-C پرتاب میشود، هندلر سیگنال سفارشی وظیفه اصلی را با فراخوانیasyncio.Task.cancel()کهasyncio.CancelledErrorرا درون وظیفه اصلی پرتاب میکند، لغو میکند. این امر باعث میشود پشته پایتون باز شود؛ میتوان از بلوکهایtry/exceptوtry/finallyبرای پاکسازی منابع استفاده کرد. پس از لغو شدن وظیفه اصلی،asyncio.Runner.run()KeyboardInterruptرا پرتاب میکند.ممکن است کاربر یک حلقه فشرده بنویسد که توسط
asyncio.Task.cancel()قابل وقفه نباشد؛ در این صورت، دومین Ctrl-C پس از آن، بلافاصلهKeyboardInterruptرا بدون لغو وظیفه اصلی پرتاب میکند.