Как использовать сокет в Python в качестве менеджера контекста?

Кажется, что было бы естественно сделать что-то вроде:

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

но Python нереализовать менеджер контекста для сокета. Могу ли я легко использовать его в качестве менеджера контекста, и если да, то как? "

 Lennart Regebro27 мая 2013 г., 14:04
@msw: во-первых, это просто еще одно подтверждение того, что "Зачем" вопросы плохие, так как они могут вызвать бесконечностьпочему бы и нет" спуск в ад. :-) Во-вторых, я думаю, вы неправильно понимаете, что такое контекстные менеджеры. Ответ "сокет не похож на файл Безразлично»не имеет никакого смысла в качестве ответа на "Зачем" вопрос в этом случае. Это'совершенно не имеет значения, что это не как файл. Менеджеры контекста не только для файлов.
 Martijn Pieters27 мая 2013 г., 15:49
@msw: обратите внимание, что закрытие действительно временное состояние; улучшить вопрос, и он может быть вновь открыт. Улучшение вопросадо это закрыто, еще лучшая идея.
 Lennart Regebro27 мая 2013 г., 15:35
@msw: я неЧтобы изменить смысл, я сделал это хорошим вопросом.
 Lennart Regebro27 мая 2013 г., 13:57
@msw: Нет.просто замаскированный вопрос почему. Хороший вопросКак использовать сокет в качестве менеджера контекста? ", Текущий вопрос, с которым я мог правильно ответить. "Оно делает" или же "Нет», или же "Да", Не очень полезно.
 Lennart Regebro27 мая 2013 г., 13:52
Зачем" вопросы в целом не очень хорошие вопросы для SO. Возможно, вы можете переписать это вкак"? :-)

Ответы на вопрос(3)

#39;низкий уровень, и на самом деле не пытается предоставить вам удобный или простой в использовании Pythonic API. Вы можете использовать что-то более высокого уровня.

Тем не менее, он на самом деле реализует менеджер контекста:

>>> with socket.socket() as s:
...   print(s)
... 
<socket.socket object,="" fd="3," family="2," type="1," proto="0">
</socket.socket>

Но вам нужно использовать Python 3.

Для совместимости с Python 2 вы можете использовать.contextlib

from contextlib import closing
import socket

with closing(socket.socket()) as s:
    print s
Решение Вопроса

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:

или использоватьcontextlib.closing() добиться того же эффекта:

from contextlib import closing

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

ноcontextmanager() Декоратор дает вам возможность сначала делать другие вещи с сокетом.

Python 3.x делаетsocket() менеджер контекста, хотя в документации не упоминается об этом. Увидетьsocket учебный класс в исходном коде, который добавляет__enter__ а также__exit__ методы.

 Martijn Pieters01 апр. 2014 г., 20:27
@RyanHaining: патч обновилсяsocket.create_connection() но это'это вроде как спрятано.
 Martijn Pieters01 апр. 2014 г., 20:26
@RyanHaining:автор патча просто забыл документировать это правильно.
 Ryan Haining01 апр. 2014 г., 20:24
Python3 /withas кажется очень полезным, я могуЯ не думаю о какой-либо причине, чтобы исключить это из документов, вы случайно не знаете, почемутам нет?
 Martijn Pieters09 нояб. 2017 г., 11:49
@Lunulata: действительно; Я исправил другую ссылку тоже. Спасибо!
 Martijn Pieters31 мая 2016 г., 21:15
@allyourcode:contextlib.closing() буду только звонитьclose на розетке. Пользовательский менеджер контекста может, скажем, привязать к открытому порту, сначала установить тайм-аут или другие параметры сокета или отправить специфичный для протокола закрывающий пакет или некоторые другие при выходе из контекста.
 Lunulata08 нояб. 2017 г., 20:55
Это должно бытьwith closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
 allyourcode31 мая 2016 г., 20:39
что подразумевается подпервый" где написанодает вам возможность сначала делать другие вещи с сокетом "? Мне кажется, что менеджер собственного контекста (то есть socketcontext) позволяет делать то же самое, что и contextlib.closing. В чем разница??

пожалуйста, следующие фрагменты для сокетов 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 в именах методов.

Ваш ответ на вопрос