Considérez le code suivant (explication ci-dessous):Python asyncio conditions de course protocole
import asyncio
class MyClass(object):
def __init__(self):
self.a = 0
def incr(self, data):
self.a += 1
print(self.a)
class GenProtocol(asyncio.SubprocessProtocol):
def __init__(self, handler, exit_future):
self.exit_future = exit_future
self.handler = handler
def pipe_data_received(self, fd, data):
if fd == 1:
self.handler(data)
else:
print('An error occurred')
def process_exited(self):
self.exit_future.set_result(True)
def start_proc(stdout_handler, *command):
loop = asyncio.get_event_loop()
exit_f = asyncio.Future(loop=loop)
subpr = loop.subprocess_exec(lambda: GenProtocol(stdout_handler, exit_f),
*command,
stdin=None)
transport, protocol = loop.run_until_complete(subpr)
@asyncio.coroutine
def waiter(exit_future):
yield from exit_future
return waiter, exit_f
def main():
my_instance = MyClass()
loop = asyncio.get_event_loop()
waiter, exit_f = start_proc(my_instance.incr, 'bash', 'myscript.sh')
loop.run_until_complete(waiter(exit_f))
loop.close()
if __name__ == '__main__':
main()
Une brève explication des componets est la suivante:
MyClass
est très simpleGenProtocol
est un class qui permet de spécifier un gestionnaire personnalisé pour les données reçues sur un stdout de sous-processus.start_proc
vous permet de démarrer un processus personnalisé spécifiant un gestionnaire personnalisé pour les données reçues sur la sortie standard, viaGenProtocol
my_proc
est un processus qui fonctionne toujours, l'envoi de données à la conduite parfois arbitraire
Maintenant, mon question est la suivante: puisque j'utilise une méthode comme gestionnaire et que cette méthode modifie un attribut d'instance de manière non atomique, est-ce potentiellement dangereux? Par exemple, lorsque je reçois de manière asynchrone des données sur le canal du sous-processus, le gestionnaire est-il appelé deux fois simultanément (risquant ainsi de corrompre les données dans MyClass.a) ou est-il sérialisé (la seconde fois que le gestionnaire est appelé le premier est fait)?
Vous pouvez utiliser les primitives de synchronisation (par exemple verrouillage) https://docs.python.org/3/library/asyncio-sync.html – kwarunek
Nous vous remercions de le pointeur! Donc, la réponse est oui, il peut y avoir des conditions de course, n'est-ce pas? –
Voir cet excellent article sur le multi-threading, la programmation asynchrone et le raisonnement local en python: [Unyielding] (https://glyph.twistedmatrix.com/2014/02/unyielding.html). – Vincent