我的问题是:
select
表示有数据需要读取,我想阅读其中的内容,我不想等待max
数量存在。 if max
< = 0然后读取等待直到遇到EOF,如果max
> 0读取块,直到可以读取max
个字节。
我不想要这个,我想阅读任何数量的选择把它放在“准备阅读”列表中。 read(1)不实用,因为这将涉及大量的读取调用。但它不能阻止。
有没有办法在select返回时找出缓冲区中存在的数量(如果它返回表示可以读取某些内容而不是超时)并读取该数量?有没有办法像套接字一样使用max
?它尽可能多地读取,然后返回?
解决方案可能是将文件置于非阻塞模式以进行读取吗?我不确定,我没想到这会“直到EOF”行为。
我会继续阅读和尝试,但我只花了30分钟左右而且没有接近,这就是我呼吁你的原因。
注意
有很多问题询问如何让recv等待一定数量的输入,并且在最大值到达之前阻止事件,我不正在寻找这个。我的问题是是阻止。
附录
setblocking(False)
没有用,我现在正在阅读如何在阅读期间使其无阻塞。我对文档给予了希望:
stdin.read Found at: sys
read([size]) -> read at most size bytes, returned as a string.
If the size argument is negative or omitted, read until EOF is reached.
Notice that when in non-blocking mode, less data than what was
requested
may be returned, even if no size parameter was given.
附录II
看起来读(0)实际读取0,这没什么,这导致无限循环,这很有趣!
对不起我似乎没有尝试过0看起来,我开始用4096(认为它会读到那里的东西......)尝试没有参数,但不是0。
我想知道read(0)的用途是什么?
附录III
我现在遇到选择问题(我试图将read(1)作为解决方案) 这是实际的代码:
def getInput(self):
log.log(log.INFO,"GetInput","Select")
readsReady = select.select((sys.stdin,),(),(),1)[0]
if len(readsReady) == 0:
#timed out
log.log(log.INFO,"GetInput","Select timed out")
if not self.toClose:
self.handler.post("GetInput")
else:
threads.getCurrentThread().removeAllHandlers()
else:
#OPTIMISED FOR READING 1
#log.log(log.INFO,"GetInput","Reading")
data = sys.stdin.read(1)
log.log(log.INFO,"GetInput","Read: "+data)
if data == "\n":
self.onInputHandler.post("OnInput",self.buffer)
self.buffer=""
else:
self.buffer+=data
self.handler.post("GetInput")
以下输出中几乎没有与此无关的东西,它们是“Hello world!”几乎立刻就出现了,并且“TEST!”约5秒钟。 “hello”是我键入的内容,输入,“k”是我后来输入的内容,输入后我按下输入一次。
输出:
0.0147 Verbose 1 SocketReader Created reader
0.0156 Verbose 2 SocketWriter Created writer
0.0260 Information 0 SocketReadWriter Created and ready for: ('localhost', 8294)
0.0268 Information 3 GetInput Select
Hello World!
1.0281 Information 3 GetInput Select timed out
1.0584 Information 3 GetInput Select
2.0593 Information 3 GetInput Select timed out
2.0896 Information 3 GetInput Select
3.0900 Information 3 GetInput Select timed out
3.1203 Information 3 GetInput Select
4.1215 Information 3 GetInput Select timed out
4.1519 Information 3 GetInput Select
TEST!
5.1524 Information 3 GetInput Select timed out
5.1828 Information 3 GetInput Select
hello
6.1467 Information 3 GetInput Read: h
6.1770 Information 3 GetInput Select
7.1782 Information 3 GetInput Select timed out
7.2086 Information 3 GetInput Select
8.2098 Information 3 GetInput Select timed out
8.2401 Information 3 GetInput Select
9.2414 Information 3 GetInput Select timed out
9.2717 Information 3 GetInput Select
10.2723 Information 3 GetInput Select timed out
10.3026 Information 3 GetInput Select
k
10.7939 Information 3 GetInput Read: e
10.8243 Information 3 GetInput Select
10.8245 Information 3 GetInput Read: l
10.8547 Information 3 GetInput Select
10.8549 Information 3 GetInput Read: l
10.8851 Information 3 GetInput Select
10.8853 Information 3 GetInput Read: o
10.9155 Information 3 GetInput Select
10.9157 Information 3 GetInput Read:
10.9459 Information 3 GetInput Select
10.9461 Information 3 GetInput Read: k
10.9763 Information 3 GetInput Select
You said: hello
11.9775 Information 3 GetInput Select timed out
12.0123 Information 3 GetInput Select
13.0133 Information 3 GetInput Select timed out
13.0437 Information 3 GetInput Select
^C13.3985 Verbose 2 Threads Thread: 2 has ended
14.0442 Information 3 GetInput Select timed out
14.0746 Information 3 GetInput Select
14.3622 Verbose 1 Threads Thread: 1 has ended
15.0758 Information 3 GetInput Select timed out
15.1363 Information 3 GetInput Select
16.1373 Information 3 GetInput Select timed out
16.1677 Verbose 3 Threads Thread: 3 has ended
这里更容易看到:http://pastebin.com/raw.php?i=H6UHHmy8
有什么奇怪的?
它读取hello的“h”,但是在k发生之前不读取“hello \ n”,如果有意义的话,它总是在1个换行符后面1个字母。
多次调用选择会导致问题吗? (在另一个线程中,套接字阅读器也使用select)
日志的格式为:
*自节目开始以来的时间
*日志级别
*线程ID(正在运行的线程中唯一)
*日志标记
*记录消息
处理程序类的功能
允许线程安全地相互发送消息,处理程序检查队列(并且任何预定的事件发生在特定时间,如TEST,发生在不同的线程上,不用担心),帖子“GetInput”调度另一个GetInput调用,将其放在队列的后面。 “OnInput”消息被传递给另一个线程的处理程序,我想要处理输入。
我这样做是因为它提供了一种处理线程的好方法,并且意味着我有一个很好的可重用代码(比如SocketReadWriter),我希望这不会导致对我的线程模型的批评,但是它确实有效。问题在于我试图获得用户输入。
你还可以看到当我按ctrl + c关闭事物时,这就是toClose的功能。当选择超时时,如果它应该关闭,它将会。线程在没有剩余处理程序时结束(处理程序仅在线程运行的函数返回后接管,此函数可能创建一个具有成员处理程序的类,因此当构造函数返回时,函数返回,有一个处理程序保持类活着)
解决方法
def getInput(self):
log.log(log.INFO,"GetInput","Select")
if sys.stdin.closed:
readsReady = []
else:
readsReady = select.select((sys.stdin,),(),(),1)[0]
if len(readsReady) == 0:
#timed out
log.log(log.INFO,"GetInput","Select timed out")
if not self.toClose:
self.handler.post("GetInput")
else:
threads.getCurrentThread().removeAllHandlers()
else:
data = sys.stdin.readline()
if len(data) == 0:
log.log(log.WARN,"GetInput","No data was returned indicating the file was closed")
self.handler.post("GetInput") #if this is a close event, the next
#timeout will deal with it
return
if data[-1] == "\n":
data = data[:-1]
log.log(log.INFO,"GetInput","Read: "+data)
self.onInputHandler.post("OnInput",data)
#if data == "\n":
# self.onInputHandler.post("OnInput",self.buffer)
# self.buffer=""
#else:
# self.buffer+=data
self.handler.post("GetInput")
def onClose(self):
#log.log(log.WARN,"Input: OnClose","Called")
self.toClose = True
sys.stdin.close()
答案 0 :(得分:4)
在os
模块中,有os.read
函数允许对文件描述符的读取进行较低级别的控制。只要至少有一个字节可以读取,它就是非阻塞的。
os.read(fd, n)
从文件描述符fd读取最多n个字节。返回包含读取字节的字符串。如果文件的末尾是由fd引用的 已到达,返回一个空字符串。
可用性:Unix,Windows。
注意:此函数适用于低级I / O,必须应用于
os.open()
或pipe()
返回的文件描述符。要读取内置函数open()
或popen()
或fdopen()
或sys.stdin
返回的“文件对象”,请使用其read()
或{{ 1}}方法。