En python2.7, le multiprocessing.Queue génère une erreur cassée lorsqu'il est initialisé depuis l'intérieur d'une fonction. Je fournis un exemple minimal qui reproduit le problème.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import multiprocessing
def main():
q = multiprocessing.Queue()
for i in range(10):
q.put(i)
if __name__ == "__main__":
main()
jette l'erreur de tuyau cassée ci-dessous
Traceback (most recent call last):
File "/usr/lib64/python2.7/multiprocessing/queues.py", line 268, in _feed
send(obj)
IOError: [Errno 32] Broken pipe
Process finished with exit code 0
Je n'arrive pas à déchiffrer pourquoi. Il serait certainement étrange que nous ne puissions pas remplir les objets Queue depuis l'intérieur d'une fonction.
Ce qui se passe ici, c'est que lorsque vous appelez main()
, il crée le Queue
, y met 10 objets et termine la fonction, ramassant toutes ses variables et objets internes, y compris le Queue
. MAIS vous obtenez cette erreur car vous essayez toujours d'envoyer le dernier numéro dans le Queue
.
de la documentation documentation :
"Lorsqu'un processus place pour la première fois un élément dans la file d'attente, un thread d'alimentation est démarré et transfère les objets d'un tampon dans le tuyau."
Comme la put()
est faite dans un autre Thread, elle ne bloque pas l'exécution du script, et permet de terminer la fonction main()
avant de terminer les opérations de la file d'attente.
Essaye ça :
#!/usr/bin/python
# -*- coding: utf-8 -*-
import multiprocessing
import time
def main():
q = multiprocessing.Queue()
for i in range(10):
print i
q.put(i)
time.sleep(0.1) # Just enough to let the Queue finish
if __name__ == "__main__":
main()
Il devrait y avoir un moyen de join
l'exécution de la file d'attente ou du bloc jusqu'à ce que l'objet soit placé dans le Queue
, vous devriez jeter un oeil dans la documentation.
Lorsque vous lancez Queue.put (), le thread implicite est démarré pour fournir des données à une file d'attente. Pendant ce temps, l'application principale est terminée et il n'y a pas de station de fin pour les données (l'objet de file d'attente est récupéré).
J'essaierais ceci:
from multiprocessing import Queue
def main():
q = Queue()
for i in range(10):
print i
q.put(i)
q.close()
q.join_thread()
if __name__ == "__main__":
main()
join_thread()
garantit que toutes les données du tampon ont été vidées. close()
doit être appelée avant join_thread()
Avec un retard en utilisant time.sleep(0.1)
comme suggéré par @HarryPotFleur, ce problème est résolu. Cependant, j'ai testé le code avec python3 et le problème de canal cassé ne se produit pas du tout en python3. Je pense que cela a été signalé comme un bug et corrigé plus tard.