我需要一种在Python中不带终止字符串(流)的缓冲区的廉价读取方法。这就是我所拥有的,但它浪费了大量的CPU时间和精力。因为它总是“尝试和捕捉”。我真的需要一种新的方法。
以下是我的代码的简化工作版本:
#! /usr/bin/env/ python
import fcntl, os, sys
if __name__ == "__main__":
f = open("/dev/urandom", "r")
fd = f.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
ready = False
line = ""
while True:
try:
char = f.read()
if char == '\r':
continue
elif char = '\n':
ready = True
else:
line += char
except:
continue
if ready:
print line
不要在终端中运行此命令。只是为了说明。”“urandom”会破坏你的终端,因为它会吐出很多随机字符,终端仿真器不管怎么解释(这会改变你当前的shell设置、标题等)。我在读通过usb连接的gps。
问题是:如果可能的话,这会占用100%的CPU使用率。我试过这个:
#! /usr/bin/env/ python
import fcntl, os, sys
if __name__ == "__main__":
f = open("/dev/urandom", "r")
fd = f.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
for line in f.readlines():
print line
但是,我得到IOError: [Errno 11] Resource temporarily unavailable
。我试着使用Popen
和其他东西。我不知所措。有人能提供一个解决方案吗(请解释一切,因为我本身不是专业人士)。另外,我应该注意到这是针对Unix的(特别是Linux,但是它必须在Linux的所有版本中都是可移植的)。
简单的解决方案是最好的:
或者,交替地
注:
让文件描述符保持阻塞模式,这样当没有可用数据时,操作系统可以阻塞您的进程(并节省CPU时间)。
在循环中使用迭代器很重要。考虑一下
for line in f.readlines():
。f.readlines()
读取所有数据,将其全部放入列表,并返回该列表。因为我们有无限的数据,f.readlines()
永远不会成功返回。相反,f
返回一个迭代器——它只获得满足下一个循环迭代所需的数据量(对于性能缓冲区,只需要多一点数据量即可)第一个版本预先读取并缓冲足够的数据以打印几行。第二个版本立即返回每一行。如果您主要关心的是节省CPU,请使用第一个版本。如果交互式响应时间是您主要关心的问题,请使用第二个。
演示:
您需要将缓冲模式设置为打开文件流时要读取的块的大小。 从python文档:
您还希望在while循环中使用readable()方法,以避免不必要的资源消耗。
但是,我建议您使用缓冲流,例如
io.BytesIO
或io.BufferedReader
更多信息请参见docs。
我决定用io。我注意到这甚至比
while True:
更精确。我正在读的gps应该每秒都会吐出信息,但我注意到它实际上是在0.95到1.05秒之间。那是我在做我的问题贴出的东西的时候。然而,当我只是
它不仅临时阻塞(这节省了cpu时间,而且有各种好处),而且它显然使缓冲区保持最新状态,因为它几乎每隔一秒就产生结果(这是我的gps最喜欢的更新时间)。
一个真正的奇迹,班级是-一个真正的奇迹-那就是如果它是唯一这样做的方式。一个人只要使用
open(file, "r")
,就可以了(这让我很生气,因为我花了一整天的时间在这上面)。相关问题 更多 >
编程相关推荐