如何在Python中使用socket作为上下文管理器?

Cha*_*Kut 41 python sockets contextmanager

看起来像做以下事情是很自然的:

with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
Run Code Online (Sandbox Code Playgroud)

但Python没有为socket实现上下文管理器.我可以轻松地将其用作上下文管理器,如果是,如何使用?

Mar*_*ers 77

socket模块相当低级,几乎可以直接访问C库功能.

您始终可以使用contextlib.contextmanager装饰器来构建自己的:

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:
Run Code Online (Sandbox Code Playgroud)

contextlib.closing()用来达到同样的效果:

from contextlib import closing

with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
Run Code Online (Sandbox Code Playgroud)

contextmanager()装饰器让你有机会先用套接字做其他事情.

Python 3.x确实构建socket()了一个上下文管理器,即使文档没有提到它.请参阅源代码中的socket,其中包含添加__enter____exit__方法.

  • Python3`with` /`as`似乎非常有用,我想不出有任何理由将其从文档中删除,你会碰巧知道它为什么不在那里吗? (3认同)
  • @RyanHaining:补丁确实更新了[`socket.create_connection()`](https://docs.python.org/3/library/socket.html#socket.create_connection),但它有点隐藏. (3认同)
  • @RyanHaining:[补丁提交者](http://bugs.python.org/issue9794)只是忘了正确记录它. (2认同)
  • @allyourcode:`contextlib.closing()`只会在socket上调用`close`.例如,自定义上下文管理器可以绑定到开放端口,首先设置超时或其他套接字选项,或者在退出上下文时发送特定于协议的关闭数据包. (2认同)

Len*_*bro 25

套接字模块只是BSD套接字接口的包装器.它是低级的,并没有真正尝试为您提供方便或易于使用的Pythonic API.你可能想要使用更高级别的东西.

也就是说,它确实实现了一个上下文管理器:

>>> with socket.socket() as s:
...   print(s)
... 
<socket.socket object, fd=3, family=2, type=1, proto=0>
Run Code Online (Sandbox Code Playgroud)

但是你需要使用Python 3.

对于Python 2兼容性,您可以使用contextlib.

from contextlib import closing
import socket

with closing(socket.socket()) as s:
    print s
Run Code Online (Sandbox Code Playgroud)