Python multiprocessamento atexit erro “Erro na atexit._run_exitfuncs”
Pergunta
Eu estou tentando executar um aplicativo simples de vários processos em Python. Os principais desova de fios 1 a processos e aguarda N até que todo o processamento feito. Os processos cada executar um loop infinito, para que possam potencialmente ser executado para sempre sem alguma interrupção de usuário, então eu coloquei em algum código para lidar com uma KeyboardInterrupt:
#!/usr/bin/env python
import sys
import time
from multiprocessing import Process
def main():
# Set up inputs..
# Spawn processes
Proc( 1).start()
Proc( 2).start()
class Proc ( Process ):
def __init__ ( self, procNum):
self.id = procNum
Process.__init__(self)
def run ( self ):
doneWork = False
while True:
try:
# Do work...
time.sleep(1)
sys.stdout.write('.')
if doneWork:
print "PROC#" + str(self.id) + " Done."
break
except KeyboardInterrupt:
print "User aborted."
sys.exit()
# Main Entry
if __name__=="__main__":
main()
O problema é que quando se usa CTRL-C para sair, eu recebo um erro adicional, embora os processos parecem sair imediatamente:
......User aborted.
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "C:\Python26\lib\atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "C:\Python26\lib\multiprocessing\util.py", line 281, in _exit_function
p.join()
File "C:\Python26\lib\multiprocessing\process.py", line 119, in join
res = self._popen.wait(timeout)
File "C:\Python26\lib\multiprocessing\forking.py", line 259, in wait
res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt
Error in sys.exitfunc:
Traceback (most recent call last):
File "C:\Python26\lib\atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "C:\Python26\lib\multiprocessing\util.py", line 281, in _exit_function
p.join()
File "C:\Python26\lib\multiprocessing\process.py", line 119, in join
res = self._popen.wait(timeout)
File "C:\Python26\lib\multiprocessing\forking.py", line 259, in wait
res = _subprocess.WaitForSingleObject(int(self._handle), msecs)
KeyboardInterrupt
Estou executando o Python 2.6 no Windows. Se há uma maneira melhor de lidar com multiprocessamento em Python, por favor me avise.
Solução
Em vez de apenas forçando sys.exit()
, você quer enviar um sinal para os seus tópicos para dizer-lhes para parar. Olhar em usar manipuladores de sinais e threads em Python.
Você poderia fazer isso alterando seu ciclo while True:
ser while keep_processing:
onde keep_processing
é algum tipo de variável global que fica situado na exceção KeyboardInterrupt. Eu não acho que esta é uma boa prática embora.