Tornado PipeIOStream: OSError: [Errno 9] Bad file descriptor
Tornado PipeIOStream: OSError: [Errno 9] Bad file descriptor
我有一个微型网络服务,它在本地存储由 ID 标识的消息。为了确保不会同时写入文件,我实现了一个队列。下面的代码只工作一次,第二次文件上传在下面抛出回溯,我真的不知道如何正确处理 fd。
from tornado import web, ioloop, gen
from tornado.queues import Queue
from tornado.iostream import PipeIOStream
class Sample:
def __init__(self):
self.queue = Queue()
@gen.coroutine
def write_queue(self):
while True:
item = yield self.queue.get()
print("Message with id %s stored" % item[0])
fd = open(item[0], 'ab')
stream = PipeIOStream(fd.fileno())
yield stream.write(item[1])
stream.close_fd()
class MainHandler(web.RequestHandler):
def initialize(self, store):
self.store = store
@gen.coroutine
def put(self, id):
yield self.store.queue.put((id, self.request.body))
def start(store):
return web.Application([
(r"/(.*)", MainHandler,
{"store": store})
])
if __name__ == '__main__':
store = Store()
app = start(store)
app.listen(8888)
ioloop.IOLoop.current().add_callback(store.write_queue)
ioloop.IOLoop.current().start()
ERROR:tornado.application:Exception in callback functools.partial(<function wrap.<locals>.null_wrapper at 0x7f46657f46a8>, <Future finished exception=OSError(9, 'Bad file descriptor')>)
Traceback (most recent call last):
stream = PipeIOStream(fd.fileno())
File "/usr/local/lib/python3.5/dist-packages/tornado/iostream.py", line 1643, in __init__
self._fio = io.FileIO(self.fd, "r+")
OSError: [Errno 9] Bad file descriptor
open
返回的文件描述符不是管道。在 PipeIOStream
上使用常规文件通常是合法的,但在 linux 上 没用 。这样的文件描述符总是被认为是可读的,从它们读取或写入它们总是阻塞的。所以像这样使用 PipeIOStream 并不比简单地做 fd.write(item[1])
更好。
你以只写模式打开了文件,但是 PipeIOStream 将它的文件包装在一个 read/write 包装器中(我真的有点惊讶这会起作用,因为真正管道是单向的)。我 认为 这就是这个异常的来源。如果您以 'ab+'
模式打开文件,我认为它会起作用。不过,我还没有尝试过。
我有一个微型网络服务,它在本地存储由 ID 标识的消息。为了确保不会同时写入文件,我实现了一个队列。下面的代码只工作一次,第二次文件上传在下面抛出回溯,我真的不知道如何正确处理 fd。
from tornado import web, ioloop, gen
from tornado.queues import Queue
from tornado.iostream import PipeIOStream
class Sample:
def __init__(self):
self.queue = Queue()
@gen.coroutine
def write_queue(self):
while True:
item = yield self.queue.get()
print("Message with id %s stored" % item[0])
fd = open(item[0], 'ab')
stream = PipeIOStream(fd.fileno())
yield stream.write(item[1])
stream.close_fd()
class MainHandler(web.RequestHandler):
def initialize(self, store):
self.store = store
@gen.coroutine
def put(self, id):
yield self.store.queue.put((id, self.request.body))
def start(store):
return web.Application([
(r"/(.*)", MainHandler,
{"store": store})
])
if __name__ == '__main__':
store = Store()
app = start(store)
app.listen(8888)
ioloop.IOLoop.current().add_callback(store.write_queue)
ioloop.IOLoop.current().start()
ERROR:tornado.application:Exception in callback functools.partial(<function wrap.<locals>.null_wrapper at 0x7f46657f46a8>, <Future finished exception=OSError(9, 'Bad file descriptor')>)
Traceback (most recent call last):
stream = PipeIOStream(fd.fileno())
File "/usr/local/lib/python3.5/dist-packages/tornado/iostream.py", line 1643, in __init__
self._fio = io.FileIO(self.fd, "r+")
OSError: [Errno 9] Bad file descriptor
open
返回的文件描述符不是管道。在PipeIOStream
上使用常规文件通常是合法的,但在 linux 上 没用 。这样的文件描述符总是被认为是可读的,从它们读取或写入它们总是阻塞的。所以像这样使用 PipeIOStream 并不比简单地做fd.write(item[1])
更好。你以只写模式打开了文件,但是 PipeIOStream 将它的文件包装在一个 read/write 包装器中(我真的有点惊讶这会起作用,因为真正管道是单向的)。我 认为 这就是这个异常的来源。如果您以
'ab+'
模式打开文件,我认为它会起作用。不过,我还没有尝试过。