¿Cómo usar socket en Python como administrador de contexto?

Parece que sería natural hacer algo como:

with socket(socket.AF_INET, socket.SOCK_DGRAM) as s: 

pero Python no implementa un administrador de contexto para socket. ¿Puedo usarlo fácilmente como administrador de contexto, y si es así, cómo?

El módulo de socket es de nivel bastante bajo, lo que le brinda acceso casi directo a la funcionalidad de la biblioteca de C.

Siempre puedes usar el decorador contextlib.contextmanager para construir el tuyo:

 import socket from contextlib import contextmanager @contextmanager def socketcontext(*args, **kw): s = socket.socket(*args, **kw) try: yield s finally: s.close() with socketcontext(socket.AF_INET, socket.SOCK_DGRAM) as s: 

o use contextlib.closing() para lograr el mismo efecto:

 from contextlib import closing with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s: 

pero el decorador contextmanager() te da la oportunidad de hacer otras cosas con el socket primero.

Python 3.x convierte a socket() un administrador de contexto, aunque la documentación no lo menciona. Consulte la clase de socket en el código fuente, que agrega los métodos __enter__ y __exit__ .

El módulo de socket es solo una envoltura alrededor de la interfaz de socket BSD. Es de bajo nivel y realmente no intenta proporcionarle una API Pythonic práctica o fácil de usar. Es posible que desee utilizar algo de nivel superior.

Dicho esto, de hecho implementa un administrador de contexto:

 >>> with socket.socket() as s: ... print(s) ...  

Pero necesitas usar Python 3.

Para la compatibilidad con Python 2 puedes usar contextlib .

 from contextlib import closing import socket with closing(socket.socket()) as s: print s 

Por favor, eche un vistazo a los siguientes fragmentos de código, tanto para sockets TCP como UDP

 import socket from contextlib import contextmanager @contextmanager def tcp_connection_to(*args, **kwargs): s = socket.create_connection(*args, **kwargs) yield s s.close() @contextmanager def udp_connection(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) yield s s.close() 

Para que puedas usarlos de la siguiente manera:

 MY_SERVER = ('localhost', 5000) # Yes, we need tuple here some_data = bytes("Hello.") with tcp_connection_to(MY_SERVER) as conn: conn.send(some_data) with udp_connection() as conn: conn.sendto(some_data, MY_SERVER) 

También he intentado enfatizar la diferencia en el comportamiento y el enfoque del término ‘conexión’ entre TCP y UDP en los nombres de los métodos.