2009-10-31 15 views
6

Piszę skrypt kopii zapasowej, który zamierzam wykonywać w cronjobie każdej nocy.Przekierowanie pliku Ouput w języku Python

Skrypt ustawia sys.stdout i sys.stderr na plik wyjściowy, aby zachować rejestr zdarzeń.

Aby wykonać kopię zapasową I użyć następującego kodu

cmd = 'rsync -av --del --stats --filter "- .thumbnails/" ' + \ 
    '--filter "- *~" --filter "- *.iso" --filter "- lost+found/" ' + \ 
    '--filter "- .cache/" --filter "- tmp/" --filter "- *.mp3" ' + \ 
    '--filter "- *.log" ' + srcDir + ' ' + dstDir 

print "Executing '"+cmd+"' ..." 
try: 
    sys.stdout.flush() 
    sys.stderr.flush() 
    retcode = subprocess.call(cmd, stdin = sys.stdin, stdout = sys.stdout, 
     stderr=sys.stderr, shell=False) 
    if retcode < 0: 
     print >>sys.stderr, "Command was terminated by signal", -retcode 
    elif retcode > 0: 
     print >>sys.stderr, "Command returned code ", retcode 
except OSError, e: 
    print >>sys.stderr, "Execution failed:", e 

dodaję wypowiedzi drukowania przed i po wywołaniu subprocess. Problem polega na tym, że przed wywołaniem otrzymuję dane wyjściowe wywołania podprocesu przed jakimkolwiek wyjściem z moich instrukcji drukowania. Dodałem wywołania flush(), ale nie ma ono żadnego efektu.

Dlaczego tak się dzieje i jak mogę zmienić to zachowanie?

+1

W jaki sposób ustawiasz sys.stdout i sys.stderr? – Ned

+1

Wydaje się poprawne i nie powinno się tak zachowywać (a nie kiedy próbuję), czy mógłbyś opisać swoje środowisko (system operacyjny, powłokę, z której uruchamiasz skrypt)? – RedGlyph

+0

Dlaczego nie używasz istniejących narzędzi, takich jak 'rsnapshot' (używa również' rsync'). – jfs

Odpowiedz

3

Właśnie znalazłem rozwiązanie here w odpowiedzi na pytanie Stackoverflow.

Wymień

sys.stderr = sys.stdout = logFile = open(tmpLogFileName, 'a') 

z

sys.stderr = sys.stdout = logFile = open(tmpLogFileName, 'a', 0) 

Mówi Pythona nie przydziela bufor wyjściowy do pliku.

+2

Ale to zbyt szybko się poddaje! :-) Chcemy pomóc ci dowiedzieć się, dlaczego flush() nie działa; jeśli po prostu wyłączysz buforowanie, prawdziwy problem - cokolwiek to było - nie zostanie naprawiony. :-) –

+0

:] To jest rozwiązanie. Nie poddaję się. Myślę, że prawdziwym problemem jest kolor. Badanie i rozwiązywanie tego wykracza poza moje kompetencje i moje potrzeby. – chmike

+0

Cóż, to była interesująca pułapka, cieszę się, że ją pokonałeś :-) – RedGlyph

0

Czy próbowałeś użyć wywoływania flush poza blokiem try?

+2

Nie, ponieważ nie powinno to mieć żadnego wpływu na zachowanie wyjścia. Wygląda na to, że kolor nie spłukuje się w rzeczywistości. Dodawanie >> sys.stdout do instrukcji "Executing" nie zmienia zachowania. – chmike

0

Dlaczego drukujesz na stderr? Jeśli podprocesy piszą na standardowe wyjście podczas pisania na stderr, może to tłumaczyć nieparzyste przeplatanie.

+2

Zakładam bloki wywołania do momentu zakończenia wywoływanego polecenia. W przeciwnym razie nie byłbym w stanie uzyskać kodu powrotu. – chmike

+0

Połączenie blokuje, jak mówisz, dzięki czemu możesz odzyskać kod powrotu. Ale to nie wyjaśnia, dlaczego drukujesz na stderr. Jeśli użyjesz tego samego pliku co podkomenda, być może dane wyjściowe będą poprawnie przeplatane. –

+1

Używam tego samego pliku, ponieważ mam instrukcję "sys.stdout = sys.stderr = logFile = open (" /tmp/backup.log "," a ")" na początku programu. Oprócz określenia stdout = sys.stdout itp. Ustawia plik log jako plik stdout dla wywoływanego polecenia. To działa.Po prostu flush() tak naprawdę nie zapisuje buforowanych danych na dysk. – chmike

Powiązane problemy