Jest to podobne do Calling coroutines in asyncio.Protocol.data_received, ale myślę, że uzasadnia to nowe pytanie.Wywołanie coroutine z asyncio.Protocol.data_received
Mam prosty serwer skonfigurować jak ten
loop.create_unix_server(lambda: protocol, path=serverSocket)
to działa dobrze, jeśli mogę to zrobić
def data_received(self, data):
data = b'data reply'
self.send(data)
mój klient otrzyma odpowiedź. Ale nie mogę uruchomić go z jakimkolwiek połączeniem asyncio
. Próbowałem wszystkich poniższych i żaden z nich nie działał.
@asyncio.coroutine
def go(self):
yield from asyncio.sleep(1, result = b'data reply')
def data_received(self, data):
print('Data Received', flush=True)
task = asyncio.get_event_loop().create_task(self.go())
data = yield from asyncio.wait_for(task,10)
self.send(data)
że jeden wisiał i nic drukowane (jeśli dobrze urządzone data_received
z @asyncio.coroutine
otrzymuję, że nie uzyskuje się z) OK, rozumiem, że za pomocą plonu w data_received
nie jest w porządku.
Gdybym wypróbować nową pętlę zdarzeń, jak poniżej, który wisi w run_until_complete
loop = asyncio.new_event_loop()
task = loop.create_task(self.go())
loop.run_until_complete(task)
data = task.result()
self.send(data)
Jeśli używam Future
, że zawiesza się również w run_until_complete
@asyncio.coroutine
def go(self, future):
yield from asyncio.sleep(1)
future.set_result(b'data reply')
def data_received(self, data):
print('Data Received', flush=True)
loop = asyncio.new_event_loop()
future = asyncio.Future(loop=loop)
asyncio.async(self.go(future))
loop.run_until_complete(future)
data = future.result()
self.send(data)
Poniższy zbliża, ale wraca natychmiast, a wynik jest typu asyncio.coroutines.CoroWrapper
, co oznacza, że linia wait_for
natychmiast powróciła z nieukończonym zadaniem?
@asyncio.coroutine
def go(self):
return(yield from asyncio.sleep(3, result = b'data reply'))
@asyncio.coroutine
def go2(self):
task = asyncio.get_event_loop().create_task(self.go())
res = yield from asyncio.wait_for(task, 10)
return result
def data_received(self, data):
print('Data Received', flush=True)
data = self.go2()
self.send(data)
Trochę utknąłem naprawdę i doceniłbym pewne wskazówki na temat tego, na co patrzeć.
Cześć, dziękuję za tę odpowiedź - to działa w moim kodzie. Po prostu integruję go z moim nietrywialnym kodem (który ma stos wywoławczy itp.) Myślałem o korzystaniu z callbacków, ale myślałem, że plonowanie/zadania/futures były nowszym podejściem i przynosiły korzyść, aby się nie martwić. o stosie wywołań lub jak uzyskać dane do twojego wywołania zwrotnego. Czy wiesz, dlaczego wewnętrzna pętla nie zakończyłaby swojej pracy? Albo dlaczego przyszłe podejście nie zadziałałoby z główną pętlą? – Dave
Och, myślę, że wewnętrzna pętla czeka na zablokowanym zewnętrznym, aby wykonać pewne IO itd. – Dave
@Dave 'asyncio' zdecydowanie preferuje podejście typu coroutine do użycia na wyższym poziomie, ale funkcje niskiego poziomu, takie jak Protokoły, nadal wykorzystują styl wywołania zwrotnego. Jeśli zamiast tego chcesz używać coroutines, [docs recommend] (https://docs.python.org/3/library/asyncio-protocol.html#coroutines-and-protocols) użyj obiektów strumieniowych zamiast protokołów. – dano