作为一个python newbe,我练习了几个任务,并遇到了“echo服务器”的示例代码。我将代码包装成面向对象的方式,然后偶然发现以下问题:由于示例代码使用选择器(使用回调方法)来复用io - 我可以保持面向对象的方法并将回调方法作为我班级定义的成员?
这个片段来自我的班级定义:
def accept(self, sock, mask):
conn, addr = sock.accept() # Should be ready
self.log.info('New connection from ' + str(addr))
conn.setblocking(False)
read_wrapper = lambda x, y: self.accept(x, y)
self.sel.register(conn, selectors.EVENT_READ, read_wrapper)
def read(self, conn, mask):
data = conn.recv(1000) # Should be ready
if data:
log.info('echoing %d bytes to %s' % (sys.getsizeof(data), conn.getpeername()))
conn.send(data) # Hope it won't block
else:
log.info('closing connection to ' + str(conn.getpeername()))
self.sel.unregister(conn)
conn.close()
def run(self):
sock = socket.socket()
sock.setblocking(False)
sock.bind((self.server_name, self.server_port))
sock.listen(10)
accept_wrapper = lambda x, y: self.accept(x, y)
self.sel.register(sock, selectors.EVENT_READ, accept_wrapper)
self.log.info('echo server up on %s:%d' % (self.server_name, self.server_port))
while True:
events = self.sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
我试图用lambda(read_wrapper和accept_wrapper)解决这个问题而没有运气 - 因为我得到了这个Traceback:
Traceback (most recent call last):
File "echo.py", line 141, in <module>
app.run()
File "echo.py", line 127, in run
callback(key.fileobj, mask)
File "echo.py", line 100, in <lambda>
read_wrapper = lambda x, y: self.accept(x, y)
File "echo.py", line 97, in accept
conn, addr = sock.accept() # Should be ready
File "/usr/lib/python3.4/socket.py", line 187, in accept
fd, addr = self._accept()
OSError: [Errno 22] Invalid argument
答案 0 :(得分:0)
不知道它是最好的解决方案还是解决方案,但它适用于闭包
def run(self):
sock = socket.socket()
sock.setblocking(False)
sock.bind((self.server_name, self.server_port))
sock.listen(10)
def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
self.log.info('echoing %d bytes to %s' % (sys.getsizeof(data), conn.getpeername()))
conn.send(data) # Hope it won't block
else:
self.log.info('closing connection to ' + str(conn.getpeername()))
self.sel.unregister(conn)
conn.close()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
self.log.info('New connection from ' + str(addr))
conn.setblocking(False)
self.sel.register(conn, selectors.EVENT_READ, read)
self.sel.register(sock, selectors.EVENT_READ, accept)
self.log.info('echo server up on %s:%d' % (self.server_name, self.server_port))
while True:
events = self.sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)