Obwohl "Multiprocessing" für die parallele Verarbeitung in Python verwendet wird, unterscheidet sich das Verhalten, wenn ein untergeordneter Prozess durch "Multiprocessing" erstellt wird, vom Verhalten eines normalen Funktionsaufrufs.
Dieses Mal wird der Einfachheit halber die Funktion "sleep_bug ()" verwendet. Dies ist eine Funktion, die "1/0" ausführt, wenn "i == 5", um einen Fehler zu erzeugen, um absichtlich einen Fehler während der Ausführung zu erzeugen.
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
'''
Wenn bei einem normalen Funktionsaufruf ein Fehler in der aufgerufenen Funktion auftritt, stoppt das Programm dort. Wenn jedoch ein mit Pool erstellter untergeordneter Prozess ausgeführt wird, um "sleep_bug ()" auszuführen, wird der untergeordnete Prozess mit einem Fehler gestoppt, der übergeordnete Prozess wird jedoch bis zum Ende fortgesetzt, ohne einen Fehler zu verursachen.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep_bug)
p.close()
p.join () #Warten Sie, bis der untergeordnete Prozess endet.
print('Done')
output
'''
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4
sleeping 5
Done
'''
Verwenden Sie r.get ()
, um sicherzustellen, dass der Fehler auch an den übergeordneten Prozess übertragen wird, wenn ein Fehler in einem untergeordneten Prozess auftritt und dieser stoppt. r.get ()
ist eine Funktion, die normalerweise darauf wartet, dass der untergeordnete Prozess beendet wird, und den Rückgabewert des untergeordneten Prozesses ausgibt. Wenn jedoch ein Fehler im untergeordneten Prozess auftritt, r.get ()
Löst eine Ausnahme aus und der übergeordnete Prozess wird dort ebenfalls gestoppt.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep_bug)
p.close()
output = r.get()
print('Done %d' % output)
# Ausgabe
'''
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
'''
Wenn Sie "Prozess" verwenden, wird ein Fehler angezeigt, der übergeordnete Prozess wird jedoch bis zum Ende fortgesetzt.
from multiprocessing import Process
p = Process(target=sleep_bug)
p.start()
p.join()
print('Done')
# Ausgabe
'''
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
'''
Im folgenden Skript wartet der untergeordnete Prozess 2 Sekunden, während er ausgeführt wird, und der übergeordnete Prozess beendet sich dort mit "sys.exit ()". Wie im folgenden Ausführungsbeispiel gezeigt, wird der untergeordnete Prozess auch dann weiter ausgeführt, wenn der übergeordnete Prozess in der Mitte stoppt.
from multiprocessing import Pool
p = Pool(1)
r = p.apply_async(sleep)
p.close()
r.wait (2) #warte 2 Sekunden für den untergeordneten Prozess
sys.exit()
# Ausgabe
'''
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