次のようなことをするのは自然なことのようです:
with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
しかし、Pythonはソケットのコンテキストマネージャーを実装していません。コンテキストマネージャーとして簡単に使用できますか。
socket
モジュールはかなり低レベルなので、Cライブラリ機能にほとんど直接アクセスできます。
いつでも _contextlib.contextmanager
_ decorator を使用して独自のコードを作成できます。
_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:
_
または contextlib.closing()
を使用して同じ効果を達成します:
_from contextlib import closing
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
_
しかし、contextmanager()
デコレータは、最初にソケットで他のことを行う機会を与えます。
Python 3.xはsocket()
をコンテキストマネージャーにします。 ___enter__
_および___exit__
_メソッドを追加するソースコードの socket
class を参照してください。
ソケットモジュールは、BSDソケットインターフェイスの単なるラッパーです。これは低レベルであり、Pythonic APIを使用するための便利な、または使いやすいものを提供しようとするものではありません。より高いレベルのものを使用することもできます。
とはいえ、実際にはコンテキストマネージャーを実装しています:
>>> with socket.socket() as s:
... print(s)
...
<socket.socket object, fd=3, family=2, type=1, proto=0>
ただし、Python 3.を使用する必要があります。
Python 2との互換性のために、contextlib
を使用できます。
from contextlib import closing
import socket
with closing(socket.socket()) as s:
print s
TCPと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()
したがって、次のように使用できます。
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)
メソッド名のTCPとUDPの間の動作と用語「接続」へのアプローチの違いを強調しようとしました。