2015-12-06 32 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