我正在尝试使用python with-statement(a.k.a。一个上下文管理器)来确保server_socket.accept()
创建的TCP连接套接字始终关闭。然而,显而易见的形式不起作用,因为accept()
返回多个值。
对于具有多个返回值的函数,有没有办法使用with语句?
下面是一个最小的例子,我想用注释代码之类的东西代替try / finally块。
#!/usr/bin/env python3
import socket
from socket import socket as Socket
with Socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind(('', 8011))
server_socket.listen(1)
print("server ready")
while True:
# with server_socket.accept() as (connection_socket, _):
# request = connection_socket.recv(1024).decode('ascii')
# reply = request.upper()
# connection_socket.send(reply.encode('ascii'))
try:
connection_socket, _ = server_socket.accept()
request = connection_socket.recv(1024).decode('ascii')
reply = request.upper()
connection_socket.send(reply.encode('ascii'))
finally:
connection_socket.close()
使用带注释的with-statement时的错误消息是:
Traceback (most recent call last):
File "./test.py", line 26, in <module>
with server_socket.accept() as (connection_socket, _):
AttributeError: __exit__
大概这是因为元组没有__exit__
所需的with
属性。
答案 0 :(得分:7)
socket.socket
的返回值有一个内置的上下文管理器,它实现__exit__
和__enter__
。 accept
返回的元组没有,但有一个库可以添加它:
import socket
import contextlib
@contextlib.contextmanager
def accept(s):
c,a = s.accept()
print('client connected on',a)
yield c,a
print('client disconnected on',a)
c.close()
with socket.socket() as s:
s.bind(('',8000))
s.listen(1)
with accept(s) as (c,a):
while True:
data = c.recv(1024)
if not data: break
c.sendall(data)
请参阅:
https://docs.python.org/3.3/library/contextlib.html
P.S。没有contextlib
:
import socket
with socket.socket() as s:
s.bind(('',8000))
s.listen(1)
with s.accept()[0] as c:
a = c.getpeername()
print('client connected on',a)
while True:
data = c.recv(1024)
if not data: break
c.sendall(data)
print('client disconnected on',a)