Python select()消耗100%CPU

时间:2019-03-01 14:13:14

标签: python sockets

我正在尝试创建一个应用程序,该应用程序创建一个套接字并打印传入的数据(出现在套接字中)。 select is the preferred method to work with sockets所以我这样写:

#!/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?

但这是代码示例占用一个CPU内核的100%

在具有无阻塞套接字的情况下,等待没有无休止循环的套接字中的数据的正确方法是什么?我需要它来检查连接是否仍然有效。有一个类似的问题CPU reaching 100% usage with select in python,但没有明确解释为什么需要某种睡眠。

2 个答案:

答案 0 :(得分:2)

调用它的方式(readers, writers, err = select([s], [s], [])),如果可读或可写,则会立即返回。但是您只检查它是否可读。

在大多数情况下,套接字可能是可写的,这正是您所要知道的。

另一种可能性是在某处添加time.sleep(0.02),例如G。当您在该循环中不执行任何其他操作时。然后,不应该担心20毫秒的额外延迟(但是,这并不干净)。

答案 1 :(得分:2)

选择最常见的用途是仅考虑rlisttimeout参数。对于您的示例代码,它应该是:

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

wlist参数仅在应用程序可能必须写入大数据时使用。在这种情况下,仅将要写入套接字的数据排队,并将套接字添加到wlist。当select返回并且有一些内容要写入套接字时,程序将尝试写入,如果仍有内容,则将其再次推送到队列中(请注意:必须推送到头部...),然后套接字保留在wlist中。如果所有内容均已写入并且队列为空,那么将从wlist中删除套接字。

在上文中,队列可以是真正的双端队列,也可以是简单的bytes缓冲区或任何其他允许在两端添加字节的容器。每个插槽应有一个。