2 votes

Filage de la queue en co-programme

Pourrais-je connecter deux coroutines A et B pour que A excite B et B excite A ? Par exemple, A accepterait un nombre, l'imprimerait et invoquerait B avec (nombre+1). B l'imprimerait et invoquerait A avec (nombre+1). Je m'attendrais à ce que 1,2,3,4,5,... soit imprimé.

Ce code fonctionne malheureusement comme prévu

def coroutine(func):
    def start(*args,**kwargs):
        cr = func(*args,**kwargs)
        cr.next()
        return cr
    return start

_target_from_a = None
_target_from_b = None

@coroutine
def func_a():
    while True:
        item = yield
        print 'a', item
        _target_from_a.send(item + 1)

@coroutine
def func_b():
    while True:
        item = yield
        print 'b', item
        _target_from_b.send(item + 1)

a = func_a()
b = func_b()
_target_from_a = b
_target_from_b = a

a.send(1)

il produit le résultat suivant erreur :

a 1
b 2
Traceback (most recent call last):
  File "coloop.py", line 31, in <module>
    a.send(1)
  File "coloop.py", line 17, in func_a
    _target_from_a.send(item + 1)
  File "coloop.py", line 24, in func_b
    _target_from_b.send(item + 1)
ValueError: generator already executing

2voto

Bakuriu Points 22607

Quand vous le faites _target_from_a.send(something) le site a coroutine, avant d'être "mis en pause" par le yield appelle b qui reprend l'exécution et ce qu'il fait est :

    item = yield
    print 'b', item
    _target_from_b.send(item + 1)   # ARGH!!

Le problème est que _target_from_b.send(item + 1) va essayer d'appeler a . Mais a à cet instant n'attend rien, il est toujours en train de s'exécuter.

Gardez à l'esprit qu'une coroutine est comme toute autre fonction lorsqu'elle s'exécute. Appeler _target_from_a.send() fait no met en pause la coroutine, mais python exécute simplement l'appel de fonction.

Résumé : Jamais faire des boucles avec des coroutines. Elles ne peuvent tout simplement pas fonctionner.

Notez que le generator already executing peut également être levée lors de l'accès au même générateur/coroutine à partir de plusieurs threads.


Je vous suggère de lire "Un cours curieux sur les Coroutines et la Concurrence" Par David Beazley, qui explique très bien comment utiliser les coroutines et comment elles fonctionnent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X