2015-12-06 30 views
4

我想將subprocess.call(...)的輸出重定向到xz-或bzip2壓縮文件。記錄並壓縮subprocess.call的輸出

我想:

with lzma.open(log_path, "x") as log_file: 
    subprocess.call(command, stdout=log_file, stderr=log_file) 

但生成的文件是不是有效的XZ壓縮文件:

$ xzcat logfile.xz 
xzcat : logfile.xz: Format de fichier inconnu 

(在法語,意爲 「未知文件格式」)。

當我只使用cat,在年底正確顯示文件,用一些奇怪的數據(在腳本中推出的命令是rsync):

& cat logfile.xz 
sending incremental file list 
prog/testfile 

sent 531.80K bytes received 2.71K bytes 1.07M bytes/sec 
total size is 14.21G speedup is 26,588.26 
�7zXZ�ִF�D!��}YZ 

logfile.xz似乎是一個半有效的XZ檔案文件,充滿未壓縮的數據。我究竟做錯了什麼 ?

PS:它的工作原理,當我做這樣的事情:

output = subprocess.check_output(command) 
log_file.write(output) 

...但鑑於該命令需要很長的時間(這是一個備份腳本),我希望能夠看到日誌(與xzcat)結束之前,要知道rsync正在做什麼。

回答

2

重新定向發生在兒童甚至執行之前的文件描述符級別:之後沒有父代碼(與子代的stdout/stderr相關)在運行之後(來自lzma模塊的Python代碼未運行)。

要壓縮的飛行,這樣你可以看到,而子進程仍在運行的輸出,你可以將其輸出重定向到xz效用:

#!/usr/bin/env python3 
import subprocess 

with open('logfile.xz', 'xb', 0) as log_file: 
    subprocess.call("command | xz -kezc -", shell=True, 
        stdout=log_file, stderr=subprocess.STDOUT) 

注:普通open()使用,不lzma.open() :壓縮在xz子流程中完成。


如果你想在純Python代碼壓縮,那麼你通過python必須管數據:

#!/usr/bin/env python3 
import lzma 
from subprocess import Popen, PIPE, STDOUT 
from shutil import copyfileobj 

with lzma.open('logfile.xz', 'xb') as log_file, \ 
    Popen('command', stdout=PIPE, stderr=STDOUT) as process: 
    copyfileobj(process.stdout, log_file) 

注:lzma.open()使用。

+0

謝謝!這個「沒有父母代碼」的東西很奇怪。我選擇使用純Python。 – Arno

+0

@YdobEmos沒有什麼奇怪的,這是管道和重定向如何在shell中工作的:'command |另一個> output.txt 2>&1' – jfs

+0

我覺得它不直觀,我希望我發送的數據在LZMA文件被寫入之前被壓縮。 (我在談論你的「沒有父代碼(與孩子的stdout/stderr有關)後運行(來自lzma模塊的Python代碼未運行)」句子)。 – Arno