select --- chờ đợi sự kiện trên một tập hợp luồng

Module này cung cấp các hàm để chờ đợi hiệu quả cho đến khi một hoặc nhiều luồng (các đối tượng giống tệp thực thi giao thức luồng, như socket, UART và các đối tượng I/O khác) sẵn sàng để đọc hoặc ghi, thay vì busy-waiting hoặc chặn trên một đối tượng duy nhất.

Đối tượng poll là giao diện được khuyến nghị: nó có thể mở rộng cho nhiều luồng và không cấp phát bộ nhớ khi sử dụng qua poll.ipoll(). Hàm select() ở cấp module là một giao diện tương thích kém hiệu quả hơn.

Ví dụ sử dụng đối tượng poll

import select

poller = select.poll()
poller.register(uart, select.POLLIN)

while True:
    # Wait up to 1000 ms for the UART to have data.
    for obj, event in poller.poll(1000):
        if event & select.POLLIN:
            print(obj.read())

Ví dụ sử dụng hàm select() ở cấp module:

import select

# Wait up to 1 second for the socket to become readable.
rlist, wlist, xlist = select.select([sock], [], [], 1.0)
if rlist:
    data = sock.recv(100)

Các hàm

select.select(rlist: List, wlist: List, xlist: List, timeout: float | None = None) Tuple[List, List, List]

Chờ cho đến khi một hoặc nhiều đối tượng luồng đã cho sẵn sàng, hoặc cho đến khi timeout hết hạn.

  • rlist là danh sách các đối tượng cần giám sát để đọc.

  • wlist là danh sách các đối tượng cần giám sát để ghi.

  • xlist là danh sách các đối tượng cần giám sát để phát hiện lỗi hoặc tình trạng treo.

  • timeout là thời gian chờ tối đa, tính bằng giây (chấp nhận số thực). Nếu bị bỏ qua hoặc là None, cuộc gọi sẽ chặn vô thời hạn; 0 trả về ngay lập tức (một lần thăm dò không chặn).

Trả về một tuple 3 phần tử gồm các danh sách (rlist, wlist, xlist). Mỗi danh sách trả về là tập con của danh sách đầu vào tương ứng chứa các đối tượng đã sẵn sàng để đọc, sẵn sàng để ghi, hoặc đã báo hiệu lỗi/treo tương ứng. Nếu timeout hết mà không có gì sẵn sàng, cả ba danh sách đều trống.

Hàm này kém hiệu quả hơn poll (nó xây dựng lại tập thăm dò nội bộ mỗi lần gọi); hãy sử dụng poll thay thế khi có thể.

Các hằng số

select.POLLIN: int

Có dữ liệu có thể đọc từ luồng.

select.POLLOUT: int

Luồng có thể chấp nhận thêm dữ liệu để ghi.

select.POLLERR: int

Đã xảy ra điều kiện lỗi trên luồng. Đây là một sự kiện không được yêu cầu: nó được báo cáo bởi poll.poll() / poll.ipoll() ngay cả khi không được yêu cầu trong eventmask, và không hợp lệ khi truyền nó như một eventmask đầu vào.

select.POLLHUP: int

Luồng đã bị treo / ngắt kết nối. Đây là một sự kiện không được yêu cầu: nó được báo cáo bởi poll.poll() / poll.ipoll() ngay cả khi không được yêu cầu trong eventmask, và không hợp lệ khi truyền nó như một eventmask đầu vào.

Các lớp

class select.poll

Tạo một đối tượng thăm dò duy trì một tập hợp các luồng đã đăng ký (hoặc bất kỳ đối tượng nào cung cấp giao thức luồng) và chờ đợi hiệu quả cho đến khi một hoặc nhiều trong số chúng có thể đọc, ghi, hoặc báo hiệu điều kiện ngoại lệ.

Các luồng được thêm vào bằng register(), xóa bằng unregister(), và tập hợp các sự kiện cần theo dõi có thể được thay đổi bằng modify(). Sau khi cấu hình, hãy gọi poll() để chặn cho đến khi có gì đó sẵn sàng (hoặc hết thời gian chờ), hoặc ipoll() để có biến thể dựa trên iterator không cấp phát bộ nhớ.

register(obj: Any, eventmask: int = select.POLLIN | select.POLLOUT) None

Đăng ký luồng obj để thăm dò, theo dõi các sự kiện được xác định bởi eventmask (phép OR logic của):

eventmask mặc định là select.POLLIN | select.POLLOUT.

select.POLLHUPselect.POLLERR không hợp lệ trong eventmask đầu vào -- chúng là các sự kiện không được yêu cầu được báo cáo bởi poll() / ipoll() bất kể chúng có được yêu cầu hay không (điều này phù hợp với ngữ nghĩa POSIX).

Có thể gọi phương thức này nhiều lần cho cùng một obj: lần gọi tiếp theo sẽ cập nhật event mask của obj, hoạt động như modify().

unregister(obj: Any) None

Xóa obj khỏi tập hợp các luồng đã đăng ký. Việc hủy đăng ký một obj chưa được đăng ký hiện tại không phải là lỗi (lần gọi không có tác dụng trong trường hợp đó).

modify(obj: Any, eventmask: int) None

Thay đổi event mask cho một obj đã đăng ký thành eventmask. Đưa ra OSError với errno.ENOENT nếu obj chưa được đăng ký.

poll(timeout: int = -1, /) List[Tuple]

Chặn cho đến khi ít nhất một luồng đã đăng ký sẵn sàng hoặc báo hiệu điều kiện ngoại lệ, sau đó trả về danh sách các luồng đã kích hoạt.

timeout là thời gian chờ tối đa tính bằng mili giây. Nếu bị bỏ qua hoặc là -1, cuộc gọi sẽ chặn vô thời hạn; 0 trả về ngay lập tức (một lần thăm dò không chặn).

Trả về danh sách các tuple (obj, event, ...), một phần tử cho mỗi luồng đã kích hoạt. obj là luồng đã đăng ký và event là phép OR theo bit của các cờ select.POLLIN / select.POLLOUT / select.POLLERR / select.POLLHUP đã xảy ra. Mỗi tuple có thể chứa thêm các phần tử được định nghĩa bởi implementation, vì vậy không nên giả định độ dài chính xác là 2. Nếu timeout hết mà không có gì sẵn sàng, một danh sách trống sẽ được trả về.

select.POLLHUPselect.POLLERR có thể được trả về bất kỳ lúc nào (ngay cả khi không được yêu cầu) và phải được xử lý -- thường bằng cách hủy đăng ký và đóng luồng bị ảnh hưởng -- nếu không các lần gọi tiếp theo sẽ tiếp tục trả về ngay lập tức với các cờ này được đặt cho luồng đó.

Mọi hàm gọi lại đã được lên lịch đang chờ xử lý đều được đảm bảo sẽ chạy trước khi vòng lặp thăm dò được bắt đầu.

Sự khác biệt so với CPython

Các tuple trả về có thể chứa nhiều hơn 2 phần tử, như đã mô tả ở trên.

ipoll(timeout: int = -1, flags: int = 0, /) Iterator[Tuple]

Tương tự như poll(), nhưng thay vì xây dựng một danh sách, nó trả về một iterator mang lại một tuple (obj, event, ...) mỗi lần. Điều này tránh cấp phát bộ nhớ mỗi lần gọi, điều quan trọng đối với các bộ lên lịch I/O bất đồng bộ.

Tuple được tạo ra là thuộc về callee: nó được tái sử dụng (ghi đè) ở lần lặp tiếp theo, vì vậy nội dung của nó phải được tiêu thụ trong thân vòng lặp và không được lưu trữ tham chiếu đến nó.

timeout có ý nghĩa tương tự như đối với poll(). Nếu flags1, hành vi one-shot được sử dụng: một luồng có sự kiện đã kích hoạt sẽ tự động xóa event mask của nó (tương đương với poll.modify(obj, 0)), vì vậy không có sự kiện nào được báo cáo thêm cho nó cho đến khi mask của nó được đặt lại bằng modify().

Mọi hàm gọi lại đã được lên lịch đang chờ xử lý đều được đảm bảo sẽ chạy trước khi vòng lặp thăm dò được bắt đầu.

Sự khác biệt so với CPython

Phương thức này là một phần mở rộng của MicroPython.