Il semble qu'il serait naturel de faire quelque chose comme:
with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
mais Python n'implémente pas de gestionnaire de contexte pour socket. Puis-je facilement l'utiliser comme gestionnaire de contexte, et si oui, comment?
Le module socket
est assez bas niveau, vous donnant un accès presque direct à la fonctionnalité de la bibliothèque C.
Vous pouvez toujours utiliser le décorateur contextlib.contextmanager
pour créer le vôtre:
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:
ou utilisez contextlib.closing()
pour obtenir le même effet:
from contextlib import closing
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
mais le décorateur contextmanager()
vous donne la possibilité de faire d'autres choses avec le socket en premier.
Python 3.x fait de socket()
un gestionnaire de contexte, même si la documentation ne le mentionne pas. Voir la classe socket
dans le code source, qui ajoute les méthodes __enter__
Et __exit__
.
Le module socket est juste un wrapper autour de l'interface socket BSD. Il est de bas niveau et n'essaie pas vraiment de vous fournir une API Pythonic pratique ou facile à utiliser. Vous voudrez peut-être utiliser quelque chose de niveau supérieur.
Cela dit, il implémente en fait un gestionnaire de contexte:
>>> with socket.socket() as s:
... print(s)
...
<socket.socket object, fd=3, family=2, type=1, proto=0>
Mais vous devez utiliser Python 3.
Pour la compatibilité Python 2, vous pouvez utiliser contextlib
.
from contextlib import closing
import socket
with closing(socket.socket()) as s:
print s
Veuillez consulter les extraits suivants, pour les deux TCP et sockets 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()
Pour que vous puissiez les utiliser de la manière suivante:
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)
J'ai également essayé de souligner la différence de comportement et d'approche du terme "connexion" entre TCP et UDP dans les noms de méthode.