Изглежда, че би било съвсем естествено да се направи нещо като:
with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
но Python не имплементира контекстен мениджър за сокет. Мога ли лесно да го използвам като контекстен мениджър и ако да, как?
Изглежда, че би било съвсем естествено да се направи нещо като:
with socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
но Python не имплементира контекстен мениджър за сокет. Мога ли лесно да го използвам като контекстен мениджър и ако да, как?
Модулът 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()
контекстен мениджър, но документацията не беше актуализирана, за да отрази това до добре в цикъла на Python 3.5, през 2016. Вижте socket
клас в изходния код, който добавя __enter__
и __exit__
методи.
with
/as
изглежда много полезен, не мога да се сетя за никаква причина да оставя това извън документите, случайно да знаете защо го няма там?
- person Ryan Haining; 01.04.2014
socket.create_connection()
, но някак си е скрита .
- person Martijn Pieters; 01.04.2014
contextlib.closing()
ще извика само close
на сокета. Персонализиран контекстен мениджър може, да речем, да се свърже с отворен порт, да зададе първо изчакване или други опции за сокет или да изпрати специфичен за протокола затварящ пакет или нещо подобно при излизане от контекста.
- person Martijn Pieters; 31.05.2016
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
- person Lunulata; 08.11.2017
Модулът на гнездото е просто обвивка около интерфейса на гнездото на 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 в имената на методите.