2013-02-26 20 views
13

Czy biblioteka Pythona logging udostępnia zserializowane rejestrowanie dla dwóch (lub więcej) oddzielnych procesów Pythona logujących się do tego samego pliku? Nie wydaje się jasne z dokumentów (które czytałem).Python: oddzielne procesy logowania do tego samego pliku?

Jeśli tak, to na zupełnie innych maszynach (gdzie udostępniony plik dziennika istniałby w eksporcie NFS dostępnym dla obu).

Odpowiedz

12

Nie jest obsługiwany. Z pytona logging cookbook:

Chociaż rejestrowanie jest thread-safe, i zalogowaniu się do pojedynczego pliku z wielu wątków w jednym procesie jest obsługiwana, logowania do jednego pliku z wielu procesów nie jest obsługiwana, ponieważ nie ma standardowego sposobu przekształcania dostępu do pojedynczego pliku w wielu procesach w Pythonie.

Następnie książka kucharska sugeruje użycie pojedynczego procesu typu gniazdo-serwer, który obsługuje dzienniki i inne procesy wysyłające do nich komunikaty dziennika. Istnieje działający przykład tego apporn w sekcji Sending and Receiving logging events across a network.

+1

Osobiście byłbym skłonny zrobić dokładnie to, co sugerują i zaimplementować bardzo mały "serwer logowania" za pomocą serwerów gniazd i po prostu zalogować się do tego gniazda, jak sugerują w książce kucharskiej. –

+1

Unikaj odpowiedzi za pomocą krótkiego zdania i linku, ale spróbuj uwzględnić treść, która rzeczywiście odpowiada na pytanie. Ułatwia to wyszukiwanie informacji w SO, a także pozwala pamiętać, że linki mogą się zepsuć w przyszłości. Jeśli chcesz dodać informacje do swojej odpowiedzi, musisz je edytować zamiast komentować. – Bakuriu

+0

Dziękuję za odpowiedź. Podejrzewałem, że tak było. Wydaje mi się, że byłoby tak samo, gdy miałem wiele demonów syslog logujących się do jednego pliku? Niestety wymóg dotyczy istnienia dzienników w udziale NFS (dostępnym z wielu różnych komputerów z tym samym kodem). Ponieważ nasze wymagania określają, że nie możemy narzucić ograniczeń, które proces musi być w stanie komunikować (mogą być w oddzielnych sieciach) i nie możemy modyfikować udziału NFS (ponieważ musi on działać po wyjęciu z pudełka z dowolnym bieżącym eksportem NFS. Wygląda na to, że będę musiał załatwić 1 log na proces w udziale NFS – sjbx

-1

Nie widzę, aby było to możliwe z powodu uprawnień dostępu do zapisu pliku;

  • Jeśli jeden proces python jest pisanie do pliku, a następnie drugi proces będzie uzyskać wyjątek IOError podczas próby otwarcia pliku.

Można ewentualnie napisać jakiś sprytny kod, który używa multiprocessing i Queue lub Lock do kolejki i dostępu do plików metr, ale byłoby to ciężka praca.

Ciekawe, dlaczego jest to ważne i czy można w ten sposób pracować w inny sposób? Może zapisywanie do dwóch plików ze znacznikami czasu, a następnie porównywanie znaczników czasu podczas wykonywania późniejszej analizy?

+1

Nie otrzymuję "IOError" podczas otwierania pliku równolegle z dwóch różnych interpretatorów. Prawdopodobnie jest to zachowanie zależne od systemu operacyjnego. – Bakuriu

+1

Książka kucharska logowania, do której odnosi się odpowiedź Haydena Crockera, nie wspomina o zezwoleniach na dostęp do zapisu jako przeszkodzie. Mówi on: "[nie jest obsługiwany], ponieważ nie ma standardowego sposobu na szeregowanie dostępu do pojedynczego pliku w wielu procesach w Pythonie." –

1

Jeden niezbyt atrakcyjna z rozwiązań tego problemu jest stworzenie procesu logowania, który nasłuchuje w gnieździe na jednej nici, które po prostu wyjść cokolwiek otrzymuje

Chodzi o to, aby przejąć kolejki gniazda jako mechanizm arbitrażowego.

#! /usr/bin/env python 

import sys 
import socket 
import argparse 

p = argparse.ArgumentParser() 
p.add_argument("-p", "--port", help="which port to listen on", type=int) 
p.add_argument("-b", "--backlog", help="accept backlog size", type=int) 
p.add_argument("-s", "--buffersize", help="recv buffer size", type=int) 
args = p.parse_args() 

port = args.port if args.port else 1339 
backlog = args.backlog if args.backlog else 5 
size = args.buffersize if args.buffersize else 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
s.bind(('', port)) 
s.listen(backlog) 
print "Listening on port ", port, 'backlog size', backlog, 'buffer size', size, '\n' 
while 1: 
    try: 
     (client, address) = s.accept() 
     data = client.recv(size) 
     print data 
    except: 
     client.close() 

I aby go przetestować:

#! /usr/bin/env python 

import sys 
import socket 
import argparse 

p = argparse.ArgumentParser() 
p.add_argument("-p", "--port", help="send port", action='store', default=1339, type=int) 
p.add_argument("text", help="text to send") 
args = p.parse_args() 

if not args.quit and not args.text: 
    p.print_help() 
else: 
    try: 
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     s.connect(('', args.port)) 
     s.send(args.text) 
    except: 
     s.close() 

następnie używać go tak:

stdbuf -o L ./logger.py -b 10 -s 4096 >>logger.log 2>&1 & 

i monitorować niedawnej działalności z:

tail -f logger.log 

każdego wpisu logowania z dowolnego dany proces będzie emitowany atomowo. Dodanie tego do standardowego systemu rejestrowania nie powinno być zbyt trudne. Korzystanie z gniazd oznacza, że ​​wiele komputerów może również kierować na pojedynczy dziennik hostowany na dedykowanym komputerze.

Powiązane problemy