Bien que le «multitraitement» soit utilisé pour le traitement parallèle en Python, le comportement lorsqu'un processus enfant est créé par le «multitraitement» présente quelques différences par rapport au comportement d'un appel de fonction normal.
Cette fois, la fonction sleep_bug ()
est utilisée par souci de simplicité. C'est une fonction qui exécute «1/0» lorsque «i == 5» pour générer une erreur afin de générer intentionnellement une erreur lors de l'exécution.
import time
def sleep_bug():
for i in range(10):
print('sleeping %d' % i)
if i == 5:
1/0
time.sleep(1)
return i
sleep_bug()
output
'''
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4
sleeping 5
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-44-d9f02a4cf7f3> in <module>
----> 1 sleep_bug()
<ipython-input-41-26bb27998e63> in sleep_bug()
12 print('sleeping %d' % i)
13 if i==5:
---> 14 1/0
15 time.sleep(1)
16
ZeroDivisionError: division by zero
'''
Dans un appel de fonction normal, si une erreur se produit dans la fonction appelée, le programme s'arrêtera là. Cependant, si un processus enfant créé à l'aide de Pool est amené à exécuter sleep_bug ()
, le processus enfant s'arrêtera avec une erreur, mais le processus parent ira jusqu'à la fin sans provoquer d'erreur.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep_bug)
p.close()
p.join () # Attendez la fin du processus enfant.
print('Done')
output
'''
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4
sleeping 5
Done
'''
Utilisez r.get ()
pour vous assurer que lorsqu'une erreur survient dans un processus enfant et qu'elle s'arrête, l'erreur est également transmise au processus parent. r.get ()
est une fonction qui attend normalement que le processus enfant se termine et affiche la valeur de retour du processus enfant, mais si une erreur se produit dans le processus enfant, r.get ()
Lèvera une exception et le processus parent s'arrêtera également là.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep_bug)
p.close()
output = r.get()
print('Done %d' % output)
# production
'''
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4
sleeping 5
---------------------------------------------------------------------------
RemoteTraceback Traceback (most recent call last)
RemoteTraceback:
"""
Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 121, in worker
result = (True, func(*args, **kwds))
File "<ipython-input-41-26bb27998e63>", line 14, in sleep_bug
1/0
ZeroDivisionError: division by zero
"""
The above exception was the direct cause of the following exception:
ZeroDivisionError Traceback (most recent call last)
<ipython-input-50-fb8f5892e1a7> in <module>
3 r = p.apply_async(sleep_bug)
4 p.close()
----> 5 output = r.get()
6 print('Done %d' % output)
/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py in get(self, timeout)
655 return self._value
656 else:
--> 657 raise self._value
658
659 def _set(self, i, obj):
ZeroDivisionError: division by zero
'''
Si vous utilisez Process
, une erreur sera affichée, mais le processus parent continuera jusqu'à la fin.
from multiprocessing import Process
p = Process(target=sleep_bug)
p.start()
p.join()
print('Done')
# production
'''
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4
sleeping 5
Process Process-35:
Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
self.run()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "<ipython-input-41-26bb27998e63>", line 14, in sleep_bug
1/0
ZeroDivisionError: division by zero
Done
'''
Le script ci-dessous attend 2 secondes pour que le processus enfant s'exécute, et le processus parent s'y termine avec sys.exit ()
. Comme indiqué dans l'exemple d'exécution ci-dessous, même si le processus parent s'arrête au milieu, le processus enfant continue de s'exécuter.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep)
p.close()
r.wait (2) # wait 2 seconds for child process
sys.exit()
# production
'''
sleeping 0
sleeping 1
An exception has occurred, use %tb to see the full traceback.
SystemExit
sleeping 2
sleeping 3
sleeping 4
sleeping 5
sleeping 6
sleeping 7
sleeping 8
sleeping 9
'''
Recommended Posts