Comment créer une boucle d'événement avec des coroutines roulantes fonctionnant pour toujours?
Afin de prévenir de la commutation de contexte, je veux créer une grande boucle pour servir à la fois les connexions réseau et des routines.
Voici la mise en œuvre de fonctions normales:
import asyncio
import time
def hello_world(loop):
print('Hello World')
loop.call_later(1, hello_world, loop)
def good_evening(loop):
print('Good Evening')
loop.call_later(1, good_evening, loop)
print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
print('step: loop.call_soon(hello_world, loop)')
loop.call_soon(hello_world, loop)
print('step: loop.call_soon(good_evening, loop)')
loop.call_soon(good_evening, loop)
try:
# Blocking call interrupted by loop.stop()
print('step: loop.run_forever()')
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
print('step: loop.close()')
loop.close()
Voici la mise en œuvre de coroutines:
import asyncio
@asyncio.coroutine
def hello_world():
while True:
yield from asyncio.sleep(1)
print('Hello World')
@asyncio.coroutine
def good_evening():
while True:
yield from asyncio.sleep(1)
print('Good Evening')
print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
try:
print('step: loop.run_until_complete()')
loop.run_until_complete(asyncio.wait([
hello_world(),
good_evening()
]))
except KeyboardInterrupt:
pass
finally:
print('step: loop.close()')
loop.close()
Et mixtes:
import asyncio
import time
def hello_world(loop):
print('Hello World')
loop.call_later(1, hello_world, loop)
def good_evening(loop):
print('Good Evening')
loop.call_later(1, good_evening, loop)
@asyncio.coroutine
def hello_world_coroutine():
while True:
yield from asyncio.sleep(1)
print('Hello World Coroutine')
@asyncio.coroutine
def good_evening_coroutine():
while True:
yield from asyncio.sleep(1)
print('Good Evening Coroutine')
print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
print('step: loop.call_soon(hello_world, loop)')
loop.call_soon(hello_world, loop)
print('step: loop.call_soon(good_evening, loop)')
loop.call_soon(good_evening, loop)
print('step: asyncio.async(hello_world_coroutine)')
asyncio.async(hello_world_coroutine())
print('step: asyncio.async(good_evening_coroutine)')
asyncio.async(good_evening_coroutine())
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
print('step: loop.close()')
loop.close()
Comme vous le voyez, chaque coroutine de la fonction de la boucle while entouré. Comment puis-je faire comme le normal? I. e. quand c'est fait, appel lui-même après le temps de retard, mais pas seulement de mettre une boucle.
source d'informationauteur changyuheng
Vous devez vous connecter pour publier un commentaire.
Si vous voulez vraiment pour éliminer le tout en boucle à partir de la coroutines (je ne sais pas pourquoi vous pensez que c'est nécessaire; c'est le moyen le plus naturel de faire ce que vous essayez de le faire), vous pouvez utiliser
asyncio.async
(ouasyncio.ensure_future
sur Python 3.4.4+) de l'annexe de la coroutine à exécuter à nouveau sur la prochaine édition de la boucle d'itération:Noter que vous devez revenir à l'aide de
loop.run_forever()
si vous faites cela, depuishello_world
/good_evening
quitter immédiatement après l'impression, maintenant.UPD
Ce code permettrait d'atteindre le maximum de profondeur de récursion. Peut-être parce que Python n'a pas de queue appel d'optimisation. Laisser le code ici comme un mauvais exemple.
Vous avez réellement essayez d'exécuter les trois exemples que vous avez donné? La différence de comportement est assez évident.
Puisque vous n'a jamais dit à quoi vous attendre, il n'est pas de dire ce qui est juste et ce qui ne l'est pas. Tous les trois implémentations pourrait être bon ou mauvais. Je peux vous dire que le comportement de chaque mise en œuvre a, et pourquoi il a un tel comportement; seulement, vous savez si il est correct.
Dans le deuxième exemple (
yield from asyncio.sleep(1)
), les deux coroutines sont exécutées simultanément. Cela signifie que chacun s'exécuter sur leur propre;hello_world
imprimeHello World
chaque seconde, etgood_evening
imprimeGood Evening
chaque seconde.Les deux autres exemples à la fois l'utilisation
time.sleep(1)
qui est bloquant. Cela signifie que lors de la première fonction (selon ce qui est; disons que c'esthello_world
) atteinttime.sleep(1)
l'ensemble du programme se bloque pendant une seconde. Cela signifie que lorsquehello_world
dort,good_evening
ne peut pas s'exécuter, et vice versa.Le programme s'exécute comme ceci:
hello_world
.time.sleep(1)
danshello_world
est atteint. Le programme dort pendant une seconde.Hello World
imprimé.hello_world
rendements.good_evening
.Good Evening
imprimé.time.sleep(1)
dansgood_evening
est atteint. Le programme dort pendant une seconde.good_evening
rendements.Donc à la fois
Hello World
etGood Evening
apparaissent chaque deux secondes, parce qu'il y a deuxtime.sleep(1)
appels entre chaqueprint
. Vous pouvez facilement notez que si vous exécutez les deux exemples.