Python select () потребляет 100% CPU - PullRequest
0 голосов
/ 01 марта 2019

Я пытаюсь создать приложение, которое создает сокет и печатает входящие данные так, как они отображаются в сокете. выбор - предпочтительный метод для работы с сокетами , поэтому я написал это:

#!/usr/bin/python3

from select import select
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 2345))
s.setblocking(False)  # True did not change anything
#s.settimeout(2)      # same behavior if uncommented

s.send(("give me data\n").encode("latin1"))

while True:
    readers, writers, err = select([s], [s], [])
    if s in readers:
        data = s.recv(1024)
        print(data)
    # some kind of sleep here?

Однако этот пример кода потребляет 100% одного ядра процессора .

Как правильно ожидать поступления данных из сокета без этого бесконечного цикла при наличии неблокирующего сокета?Мне нужно, чтобы проверить, если соединение еще жив.Есть похожий вопрос Процессор достигает 100% использования с помощью select в python , но он не дает четкого объяснения, почему необходим какой-то сон.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Наиболее распространенное использование для выбора - это учитывать только параметры rlist и timeout.Для вашего примера кода это должно быть:

while True:
    readers, writers, err = select([s], [], [])
    if s in readers:
        data = s.recv(1024)
        print(data)

Параметр wlist используется только тогда, когда приложению может потребоваться записать большие данные.В этом случае данные для записи в сокет просто ставятся в очередь, и сокет добавляется в wlist.Когда возвращается select и есть что-то для записи в сокет, программа пытается записать, и если что-то остается, она снова помещается в очередь (будьте осторожны: нужно вставить в головную часть ...) и сокетосталось в wlist.Если все написано и очередь пуста, сокет удаляется из wlist.

. В приведенном выше тексте очередь может быть истинной двойной конечной очередью или простой bytes буфер или любой другой контейнер, позволяющий добавлять байты на обоих концах.Один должен существовать в сокете.

0 голосов
/ 01 марта 2019

Как вы его называете (readers, writers, err = select([s], [s], [])), он сразу же возвращается, если он доступен для чтения или записи.Но вы только проверяете, доступен ли он для чтения.

Поскольку сокет, вероятно, доступен для записи в большинстве случаев, это именно то, что вам говорят.

Другой возможностью может быть добавление куда-нибудь time.sleep(0.02)Например, когда вы ничего не делаете в этом цикле.Тогда 20 мс дополнительной задержки не должны повредить (однако, это не чисто).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...