10

我的问题是:

select表示有要读取的数据,我想读取那里的任何内容,我不想等待max数量存在。如果max<= 0 则 read 等待直到遇到 EOF,如果max>0 则 read 阻塞直到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.

附录二

看来read(0)其实读的是0,也就是什么都没有,这样会导致死循环,有意思!

很抱歉,我似乎实际上并没有尝试 0,我从 4096 开始(认为它会读取那里的任何内容....)尝试不带参数,但不带 0。

我想知道 read(0) 有什么用?

附录三

我现在遇到了 select 问题(我尝试将 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!” 几乎立即通过,“测试!” 大约 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(在运行线程中唯一)

*日志标签

*日志消息

Handler 类的作用

是允许线程彼此安全地发布消息,处理程序检查队列(以及在特定时间发生的任何预定事件,例如发生在不同线程上的测试,不要担心),“GetInput”的帖子安排另一个对 GetInput 的调用,将其放在队列的后面。“OnInput”消息被传递给另一个线程的处理程序,我想处理输入。

我这样做是因为它提供了一种处理线程的好方法,并且意味着我有很好的可重用代码(如 SocketReadWriter),我希望这不会导致对我的线程模型的批评,但它确实有效. 问题在于我尝试获取用户输入。

您还可以看到当我执行 ctrl+c 时,事情会关闭,这就是 toClose 事情的作用。当 select 超时时,如果它应该关闭,它将关闭。线程在没有处理程序时结束(处理程序仅在线程要运行的函数返回后接管,该函数可能会创建一个具有成员处理程序的类,因此当构造函数返回时,函数返回,有一个处理程序保持类活着)

解决方法

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()
4

1 回答 1

5

os模块中,有一个os.read函数允许对从文件描述符的读取进行较低级别的控制。只要至少有一个字节可供读取,它就是非阻塞的。

os.read(fd, n)

从文件描述符 fd 中最多读取 n 个字节。返回包含读取的字节的字符串。如果已到达 fd 引用的文件的末尾,则返回一个空字符串。

可用性:Unix、Windows。

os.open()注意:此函数适用于低级 I/O,并且必须应用于由or返回的文件描述符pipe()。要读取由内置函数open()popen()or fdopen(), or返回的“文件对象” sys.stdin,请使用其read()orreadline()方法。

于 2013-09-21T22:38:25.773 回答