حلقه رویداد¶
کد منبع: 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() میتواند با تنظیم یک سیاست حلقه رویداد سفارشی تغییر کند.
فهرست
این صفحهی مستندات شامل بخشهای زیر است:
بخش Event Loop Methods مستندات مرجع APIهای حلقه رویداد است؛
بخش Callback Handles نمونههای
HandleوTimerHandleرا که از متدهای زمانبندی مانندloop.call_soon()وloop.call_later()بازگردانده میشوند، توضیح میدهد؛بخش Server Objects انواعی را که از متدهای حلقه رویداد مانند
loop.create_server()بازگشت داده میشوند، توضیح میدهد؛بخش Event Loop Implementations، کلاسهای
SelectorEventLoopوProactorEventLoopرا مستند میکند؛بخش Examples چگونگی کار با برخی از APIهای حلقه رویداد را نشان میدهد.
متدهای حلقه رویداد¶
حلقههای رویداد 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)¶
بستن اجراکنندهی پیشفرض را زمانبندی میکند و منتظر میماند تا همهی نخهای موجود در
ThreadPoolExecutorjoin شوند. پس از فراخوانی این متد، استفاده از اجراکنندهی پیشفرض با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)برمیگرداند.خلاصهای از ترتیب زمانی عملیات زیربنایی به شرح زیر است:
اتصال برقرار میشود و یک transport برای آن ایجاد میشود.
protocol_factory بدون آرگومان فراخوانی میشود و انتظار میرود نمونهای از protocol را برگرداند.
نمونهی پروتکل با فراخوانی متد
connection_made()خود، به انتقال متصل میشود.در صورت موفقیت، یک تاپل
(transport, protocol)برگردانده میشود.
انتقال ایجادشده، یک جریان دوطرفه وابسته به پیادهسازی است.
آرگومانهای دیگر:
ssl: اگر داده شده باشد و false نباشد، یک انتقال SSL/TLS ایجاد میشود (بهطور پیشفرض یک انتقال TCP ساده ایجاد میشود). اگر ssl یک شیء
ssl.SSLContextباشد، از این زمینه برای ایجاد انتقال استفاده میشود؛ اگر sslTrueباشد، از یک زمینه پیشفرض که ازssl.create_default_context()بازگشت داده میشود، استفاده میشود.همچنین ملاحظه نمائید
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()را ببینید.دسترسپذیری: Unix.
تغییر یافته در نسخهی 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()را ببینید.دسترسپذیری: Unix.
تغییر یافته در نسخهی 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نیست.همچنین ملاحظه نمائید
- async loop.sock_accept(sock)¶
یک اتصال را میپذیرد. بر اساس متد مسدودکنندهی
socket.accept()مدلسازی شده است.سوکت باید به یک نشانی مقید شده باشد و در حال گوش دادن به اتصالها باشد. مقدار بازگشتی یک جفت
(conn, address)است که در آن conn یک شیء سوکت جدید قابل استفاده برای ارسال و دریافت داده روی اتصال است، و address نشانی است که به سوکت در طرف دیگر اتصال مقید شده است.sock باید سوکتی غیرمسدود باشد.
تغییر یافته در نسخهی 3.7: با وجود اینکه این متد همیشه بهعنوان یک متد همروال مستند شده بود، پیش از پایتون 3.7 یک
Futureرا برمیگرداند. از پایتون 3.7، این یک متدasync defاست.همچنین ملاحظه نمائید
- 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.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را برمیگرداند.دسترسپذیری: Unix.
همچنین ملاحظه نمائید
ماژول 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¶
از این ویژگی میتوان برای تنظیم حداقل مدت زمان اجرا بر حسب ثانیه که «کند» در نظر گرفته میشود، استفاده کرد. هنگامی که حالت اشکالزدایی فعال باشد، کالبکهای «کند» ثبت میشوند.
مقدار پیشفرض ۱۰۰ میلیثانیه است.
همچنین ملاحظه نمائید
اجرای زیرفرایندها¶
متدهای توصیفشده در این زیربخش سطح پایین هستند. در کد معمول ناهمگام/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 باید فهرستی از رشتهها باشد که بهصورت زیر نمایش داده میشود:
str;یا
bytes، که با کدگذاری سامانه فایلبندی کدگذاری شده است.
اولین رشته، پرونده اجرایی برنامه را مشخص میکند و رشتههای باقیمانده آرگومانها را مشخص میکنند. آرگومانهای رشتهای با هم،
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) استفاده میکند.دسترسپذیری: Windows.
همچنین ملاحظه نمائید
مستندات MSDN درباره پورتهای تکمیل ورودی/خروجی (I/O Completion Ports).
- 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()
نمایش تاریخ فعلی با 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()
همچنین ملاحظه نمائید
یک مثال مشابه با استفاده از انتقالها، پروتکلها و متد
loop.create_connection().یک مثال مشابه دیگر که از تابع سطح بالای
asyncio.open_connection()و جریانها استفاده میکند.
تنظیم هندلرهای سیگنال برای 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())