2017-10-19 2 views
1

Ich habe ein gleichzeitig ausgeführtes Programm, wo ich ein Protokoll für jeden untergeordneten Prozess erstellen möchte. Ich beschreibe zuerst mein Setup und dann das Problem, vor dem ich stehe. Hier sind meine primären Module:Probleme mit Pythons Multithreading/Logging-Modulen

mp_handler.py:

import logging 
import multiprocessing as mp 

def mp_handler(target, args_list): 

    # configure logs 
    for args in args_list: 
     logger_id = args[0] # first arg suffices to id a process, in my case 
     logger = logging.getLogger(logger_id) 
     handler = logging.FileHandler(logger_id + '.log') 
     logger.setLevel(logging.INFO) 
     logger.addHandler(handler) 

    mp.set_start_method('spawn') # bug fix, see below   

    # build each process 
    for args in args_list: 
     p = mp.Process(target = target, args = args) 
     p.start() 

mp_worker.py:

import logging 
from deco_module import deco 
from my_module import function_with_open_cv 

@deco 
def mp_worker(args): 
    logger_id = arg[0] 
    logger = logging.getLogger(logger_id) 

    log.info("Information about process %s" % log_id)   

    # do a lot of stuff with openCV3 
    function_with_open_cv(args)  # also logs to this child's log file 

deco_module.py: Dieses Modul hat einige Handhabung Ausnahme, und ich habe keine Ahnung, warum es könnte stören, aber ich denke, ich würde es für alle Fälle einschließen.

Nun zu meinem Problem. Ich habe den in diesem Beitrag beschriebenen Fehler erhalten: https://github.com/opencv/opencv/issues/5150. Daher schrieb ich die mp.set_start_method('spawn') Zeile in mp_handler().

Nach Debuggen jedoch fand ich, dass diese Linie verursacht die logger = logging.getLogger(logger_id) Linie mp_worker() einen NEUEN Logger zu schaffen, im Gegensatz zu dem in der Mutter erstellt bekommen, das heißt mp_handler(). Ich konnte dies sehen, indem ich hex(id(logger)) in den Eltern- und den Kind-Modulen druckte und sehe, dass die Speicherorte unterschiedlich sind. In der Tat, wie ich bereits sagte, vermeidet das Schreiben von mp.set_start_method('fork') dieses Problem (das macht für mich sehr groben Sinn, da mein Verständnis ist, dass Spawn einen neuen Platz für den Logger schaffen wird).

Hauptproblem: Also, das Problem ist, wie arbeite ich um die Tatsache, dass ich brauche die Start-Methode auf 'spawn' für OpenCV gesetzt werden, aber müssen es ausschalten, um für die Protokoll-Kommunikation zwischen Module (dh damit mp_worker seine korrekte logger_id erkennt, um sich in die richtige Datei einzuloggen)? Im Rahmen der guten Praxis möchte ich alle Logging-Konfigurationen sowohl für die untergeordneten als auch für die untergeordneten Module beibehalten.

sekundäres Problem: Angenommen, ich ignoriere die Tatsache, dass ich OpenCV brauche und setze die Methode auf 'fork.' In diesem Fall habe ich festgestellt, dass keine der logging.info() Anweisungen in der function_with_open_cv() Funktion nie zum Protokoll gelangt! Angenommen, Ihre Empfehlung beinhaltet, dass Sie sie auf "fork" setzen. Worum geht es hier? EDIT: FIXED! Dies wird auch durch OpenCV verursacht. Das Problem besteht also immer noch ... Wie verwende ich einen Spawn-Prozess und verliere meine Logger-ID nicht?

Vielen Dank!

Antwort

-1

Sie sollten die Protokollierung nicht konfigurieren, bevor ein Prozess gestartet wird, sondern danach. Ein Beispiel, wie es richtig gemacht wird, finden Sie unter the documentation. Dies gilt für Python 3, aber wenn Sie es unter Python 2 ausführen müssen, können Sie die logutils package verwenden, die QueueListener und QueueHandler Klassen bereitstellt.

Das Logging-Kochbuch enthält mehr Beispielcode für die Verwendung der Protokollierung mit multiprocessing.

+0

Dies wäre eine viel bessere Antwort, wenn Sie etwas ins Detail gehen, was hier schief geht. –

+0

@SamHartman das ist kein Grund zum Downvote. Es ist nicht wirklich möglich, Threading, Forking und deren Interaktionen relativ übersichtlich zu erklären. –

+0

Ich habe abgelehnt, weil ich dachte, dass Sie die Frage nicht beantwortet haben: Insbesondere dachte ich, dass ein Teil der Frage fragte, was los sei. Ich merke jedoch, dass das OP nur danach gefragt hat, wie man es beheben kann. In einer ausreichend komplexen Anwendung glaube ich nicht, dass dies eine gute Antwort ist, aber ich bedaure den Downvote. Ohne eine Bearbeitung kann ich mich nicht ändern. –