Possiedo un programma possibilmente long che attualmente ha 4 processi, ma potrebbe essere configurato per avere di più. Ho ricercato logging from multiple processes usando python logging
e sto usando l'approccio SocketHandler discusso here. Non ho mai avuto problemi con un unico logger (senza prese), ma da quello che ho letto mi è stato detto che sarebbe fallito alla fine e inaspettatamente. Per quanto ne so è sconosciuto cosa succederà quando proverai a scrivere sullo stesso file nello stesso momento. Il mio codice fa essenzialmente i seguenti:Registrazione di Python da più processi
import logging
log = logging.getLogger(__name__)
def monitor(...):
# Spawn child processes with os.fork()
# os.wait() and act accordingly
def main():
log_server_pid = os.fork()
if log_server_pid == 0:
# Create a LogRecordSocketServer (daemon)
...
sys.exit(0)
# Add SocketHandler to root logger
...
monitor(<configuration stuff>)
if __name__ == "__main__":
main()
Quindi le mie domande sono: Ho bisogno di creare un nuovo oggetto log
dopo ogni os.fork()
? Cosa succede all'attuale oggetto globale log
?
Con il fare le cose come sono, riesco anche a risolvere il problema che sto cercando di evitare (più file aperti/socket)? Questo fallirà e perché fallirà (mi piacerebbe essere in grado di dire se future implementazioni simili falliranno)?
Inoltre, in che modo il metodo "normale" (un'espressione log=
) di registrazione su un file da più processi non riesce? Alza un IOError/OSError? O semplicemente non scrive completamente i dati nel file?
Se qualcuno potesse fornire una risposta o dei collegamenti per aiutarmi, sarebbe grandioso. Grazie.
FYI: sto testando su Mac OS X Lion e il codice sarà probabilmente a finire in esecuzione su un CentOS 6 VM su una macchina Windows (se quello che conta). Qualunque sia la soluzione che uso non ha bisogno di lavorare su Windows, ma dovrebbe funzionare su un sistema basato su Unix.
UPDATE: Questa domanda ha iniziato ad allontanarsi dalla registrazione di comportamenti specifici ed è più nel regno di ciò che fa Linux con i descrittori di file durante i fork. Ho tirato fuori uno dei miei libri di testo del college e sembra che se apri un file in modalità append da due processi (non prima di un fork) che entrambi saranno in grado di scrivere correttamente nel file purché la tua scrittura non superi il vero buffer del kernel (sebbene potrebbe essere necessario utilizzare il buffering di riga, non è ancora sicuro su quello). Questo crea 2 voci di tabella file e una voce di tabella v-nodo. L'apertura di un file quindi non dovrebbe funzionare, ma sembra che non superi il buffer del kernel come prima (l'ho fatto in un programma precedente).
Quindi, suppongo che, se si desidera la registrazione multiprocessing indipendente dalla piattaforma, si utilizzano socket e si crea un nuovo SocketHandler dopo ogni fork per essere sicuri, come suggerito da Vinay di seguito (che dovrebbe funzionare ovunque). Per me, dal momento che ho un forte controllo su quale sistema operativo viene eseguito il mio software, penso che andrò con un oggetto globale log
con un FileHandler (si apre in modalità di aggiunta per impostazione predefinita e con buffer di riga sulla maggior parte dei SO). La documentazione per open
dice "Un buffer negativo significa utilizzare l'impostazione predefinita di sistema, che di solito è la linea bufferizzata per i dispositivi tty e completamente bufferizzata per altri file. Se omessa, viene utilizzata l'impostazione predefinita del sistema." oppure potrei semplicemente creare il mio flusso di registrazione per essere sicuro del buffer di linea. E tanto per essere chiari, io sto bene con:
# Process A
a_file.write("A\n")
a_file.write("A\n")
# Process B
a_file.write("B\n")
produzione ...
A\n
B\n
A\n
fintanto che non produce ...
AB\n
\n
A\n
Vinay (o chiunque altro), quanto sia sbagliato sono io? Fammi sapere. Grazie per la maggiore chiarezza/sicurezza che puoi fornire.
I thread e i blocchi sono utili per cose come questa ... –
Ho bisogno di processi separati mentre i bambini stanno comunicando con dispositivi esterni che dovrebbero essere il più "veloci" possibile. – daveydave400
Ho aggiornato la mia risposta. –