selectors --- تسهیم سطح بالای I/O (multiplexing)

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

کد منبع: Lib/selectors.py


مقدمه

این ماژول امکان تسهیم ورودی/خروجی (I/O multiplexing) سطح بالا و کارآمد را فراهم می‌کند و بر پایه‌ی سازوکارهای اولیه‌ی ماژول select ساخته شده است. کاربران تشویق می‌شوند به جای آن از این ماژول استفاده کنند، مگر اینکه بخواهند کنترل دقیقی بر سازوکارهای اولیه‌ی سطح سیستم‌عامل استفاده‌شده داشته باشند.

یک کلاس پایه انتزاعی BaseSelector به همراه چند پیاده‌سازی عینی (KqueueSelector، EpollSelector...) تعریف می‌شود که می‌توان از آن‌ها برای انتظار دریافت اعلان آمادگی I/O روی چندین شیء پرونده استفاده کرد. در ادامه، «file object» به هر شیء دارای متد fileno()، یا یک توصیف‌گر پرونده خام اشاره دارد. به file object مراجعه کنید.

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

توجه

نوع اشیای پرونده پشتیبانی‌شده به سکو بستگی دارد: در ویندوز، سوکت‌ها پشتیبانی می‌شوند، اما پایپ‌ها پشتیبانی نمی‌شوند، در حالی که در یونیکس، هر دو پشتیبانی می‌شوند (ممکن است انواع دیگری نیز پشتیبانی شوند، مانند fifos یا دستگاه‌های پرونده ویژه).

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

select

ماژول مالتی‌پلکسینگ (multiplexing) ورودی/خروجی سطح پایین.

دسترس‌پذیری: not WASI.

این ماژول روی WebAssembly کار نمی‌کند یا در دسترس نیست. برای اطلاعات بیشتر سکوهای WebAssembly را ببینید.

کلاس‌ها

سلسله‌مراتب کلاس‌ها:

BaseSelector
+-- SelectSelector
+-- PollSelector
+-- EpollSelector
+-- DevpollSelector
+-- KqueueSelector

در ادامه، events یک نقاب بیتی (bitwise mask) است که نشان می‌دهد برای کدام رویدادهای ورودی/خروجی باید روی یک شیء پرونده داده‌شده منتظر ماند. این می‌تواند ترکیبی از ثابت‌های ماژول در زیر باشد:

ثابت

معنی

selectors.EVENT_READ

در دسترس برای خواندن

selectors.EVENT_WRITE

در دسترس برای نوشتن

class selectors.SelectorKey

SelectorKey یک namedtuple است که برای مرتبط کردن یک شیء پرونده با توصیف‌گر پرونده زیربنایی، نقاب رویداد انتخاب‌شده و داده‌ی پیوست‌شده‌ی آن استفاده می‌شود. این شیء توسط چندین متد BaseSelector برگردانده می‌شود.

fileobj

شیء پرونده ثبت شد.

fd

توصیف‌گر پرونده زیربنایی.

events

رویدادهایی که باید روی این شیء پرونده منتظر آن‌ها ماند.

data

داده‌های غیرشفاف اختیاری مرتبط با این شیء پرونده: برای مثال، می‌توان از این داده‌ها برای ذخیره‌ی شناسه‌ی نشست به ازای هر کلاینت استفاده کرد.

class selectors.BaseSelector

BaseSelector برای انتظار برای آمادگی رویدادهای I/O روی چندین شیء پرونده استفاده می‌شود. این کلاس از ثبت جریان‌های پرونده، لغو ثبت آن‌ها و متدی برای انتظار برای رویدادهای I/O روی آن جریان‌ها، با مهلت زمانی اختیاری، پشتیبانی می‌کند. این کلاس یک کلاس پایه انتزاعی است، بنابراین نمی‌توان آن را نمونه‌سازی کرد. به‌جای آن از DefaultSelector استفاده کنید، یا اگر می‌خواهید به‌طور خاص از یک پیاده‌سازی مشخص استفاده کنید و سکوی شما از آن پشتیبانی می‌کند، از یکی از SelectSelector، KqueueSelector و غیره استفاده کنید. BaseSelector و پیاده‌سازی‌های عینی آن از پروتکل context manager پشتیبانی می‌کنند.

abstractmethod register(fileobj, events, data=None)

یک شیء پرونده را برای انتخاب ثبت کنید و آن را برای رویدادهای ورودی/خروجی پایش کنید.

fileobj شیء پرونده‌ای است که باید پایش شود. این می‌تواند یک توصیف‌گر پرونده از نوع عدد صحیح یا یک شیء دارای متد fileno() باشد. events یک نقاب بیت‌به‌بیت (bitwise mask) از رویدادهای مورد پایش است. data یک شیء غیرشفاف (opaque object) است.

این یک نمونه جدید از SelectorKey برمی‌گرداند، یا در صورت نامعتبر بودن نقاب رویداد یا توصیف‌گر پرونده، یک ValueError پرتاب می‌کند، یا اگر شیء پرونده از قبل ثبت‌شده باشد، یک KeyError پرتاب می‌کند.

abstractmethod unregister(fileobj)

ثبت یک شیء پرونده را برای انتخاب لغو می‌کند و آن را از پایش خارج می‌کند. یک شیء پرونده باید پیش از بسته‌شدن، لغو ثبت شود.

fileobj باید یک شیء پرونده باشد که پیش‌تر ثبت شده است.

این، نمونه‌ی مرتبط SelectorKey را برمی‌گرداند، یا اگر fileobj ثبت‌نشده باشد، یک KeyError پرتاب می‌کند. این در صورتی که fileobj نامعتبر باشد، یک ValueError پرتاب خواهد کرد (برای مثال، اگر متد fileno() نداشته باشد یا متد fileno() آن مقدار بازگشتی نامعتبری داشته باشد).

modify(fileobj, events, data=None)

تغییر رویدادهای پایش‌شده یا داده‌ی پیوست‌شده‌ی یک شیء پرونده ثبت‌شده.

این معادل BaseSelector.unregister(fileobj) و سپس BaseSelector.register(fileobj, events, data) است، با این تفاوت که می‌تواند به‌صورت کارآمدتری پیاده‌سازی شود.

این یک نمونه جدید از SelectorKey را برمی‌گرداند، یا در صورت نامعتبر بودن نقاب رویداد یا توصیف‌گر پرونده، ValueError پرتاب می‌کند، یا اگر شیء پرونده ثبت‌نشده باشد، KeyError پرتاب می‌کند.

abstractmethod select(timeout=None)

منتظر بمانید تا برخی از شیءهای پرونده ثبت‌شده آماده شوند، یا مهلت به پایان برسد.

اگر timeout > 0 باشد، این حداکثر مهلت زمانی را بر حسب ثانیه مشخص می‌کند. اگر timeout <= 0 باشد، فراخوانی مسدود نمی‌شود و اشیای پرونده‌ای را که در حال حاضر آماده‌اند گزارش می‌کند. اگر timeout برابر None باشد، فراخوانی تا زمانی که یک شیء پرونده پایش‌شده آماده شود مسدود می‌شود.

این، فهرستی از تاپل‌های (key, events) را برمی‌گرداند، یکی برای هر شیء پرونده آماده.

key نمونه‌ی SelectorKey متناظر با یک شیء پرونده آماده است. events یک نقاب بیتی (bitmask) از رویدادهای آماده برای این شیء پرونده است.

توجه

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

تغییر یافته در نسخه‌ی 3.5: اکنون انتخابگر (selector) به جای برگرداندن یک فهرست خالی از رویدادها پیش از پایان مهلت، هنگامی که با یک سیگنال قطع شود و هندلر سیگنال استثنایی پرتاب نکرده باشد، با یک مهلت بازمحاسبه‌شده دوباره تلاش می‌شود (برای چرایی این موضوع PEP 475 را ببینید).

close()

انتخابگر را ببندید.

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

get_key(fileobj)

کلید مرتبط با یک شیء پرونده ثبت‌شده را برمی‌گرداند.

این نمونه‌ی SelectorKey مرتبط با این شیء پرونده را برمی‌گرداند، یا در صورتی که شیء پرونده ثبت‌شده نباشد، KeyError را پرتاب می‌کند.

abstractmethod get_map()

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

این یک نمونه‌ی Mapping را برمی‌گرداند که اشیای پرونده ثبت‌شده را به نمونه‌های SelectorKey مرتبط با آن‌ها نگاشت می‌کند.

class selectors.DefaultSelector

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

class selectors.SelectSelector

انتخابگر مبتنی بر select.select().

class selectors.PollSelector

انتخابگر مبتنی بر select.poll().

class selectors.EpollSelector

انتخاب‌گر مبتنی بر select.epoll().

fileno()

این، توصیف‌گر پرونده‌ای را که توسط شیء select.epoll() زیربنایی استفاده می‌شود، بازمی‌گرداند.

class selectors.DevpollSelector

انتخابگر مبتنی بر select.devpoll().

fileno()

این توصیف‌گر پرونده‌ای را برمی‌گرداند که شیء زیربنایی select.devpoll() از آن استفاده می‌کند.

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

class selectors.KqueueSelector

انتخابگر مبتنی بر select.kqueue().

fileno()

این، توصیف‌گر پرونده‌ای را برمی‌گرداند که توسط شیء زیربنایی select.kqueue() استفاده می‌شود.

مثال‌ها

در اینجا پیاده‌سازی ساده‌ای از سرور پژواک (echo server) آمده است:

import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print('accepted', conn, 'from', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        print('echoing', repr(data), 'to', conn)
        conn.send(data)  # Hope it won't block
    else:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)