如何使用Python复制和提取.gz文件

4

我刚开始学习Python,有一个问题。

如何创建一个脚本来完成以下操作:(我将介绍如何在Bash中完成)

  1. 从远程server1复制<file>.gz到本地存储。

    cp /dumps/server1/file1.gz /local/

  2. 然后在本地解压该文件。

    gunzip /local/file1.gz

  3. 然后将提取的文件复制到远程server2(用于归档和去重)

    cp /local/file1.dump /dedupmount

  4. 删除本地的.gz文件以释放“临时”存储空间

    rm -rf /local/file1.gz

我需要循环运行所有这些操作以处理所有文件。 所有文件和目录都在同一台服务器上进行NFS挂载。

for循环遍历/dump/文件夹并查找.gz文件。 每个.gz文件首先将被复制到/local目录,然后在那里提取。 提取后,解压缩的.dmp文件将被复制到/dedupmount文件夹进行归档。

我只是在思考如何编写这个脚本。

2个回答

17

Python解决方案

尽管shell代码可能更短,但整个过程可以在Python中本地完成。 Python解决方案的关键点是:

  • 使用gzip模块,读取gzip压缩文件与普通文件一样简单。

  • 要获取源文件列表,请使用glob模块。 它是按照shell glob功能建模的。

  • 要操作路径,请使用Python的os.path模块。 它提供了一个与操作系统无关的文件系统接口。

这里是示例代码:

import gzip
import glob
import os.path
source_dir = "/dumps/server1"
dest_dir = "/dedupmount"

for src_name in glob.glob(os.path.join(source_dir, '*.gz')):
    base = os.path.basename(src_name)
    dest_name = os.path.join(dest_dir, base[:-3])
    with gzip.open(src_name, 'rb') as infile:
        with open(dest_name, 'wb') as outfile:
            for line in infile:
                outfile.write(line)

这段代码从remote1服务器读取并写入remote2服务器,除非您需要一个本地副本,否则不需要。

在此代码中,所有解压缩都是由本地计算机上的CPU完成的。

Shell代码

为了比较,这里是等效的Shell代码:

for src in /dumps/server1/*.gz
do
    base=${src##*/}
    dest="/dedupmount/${base%.gz}"
    zcat "$src" >"$dest"
done

Python 三步代码

这种稍微复杂一些的方法实现了原帖中的三步算法,该算法使用本地机器上的临时文件:

import gzip
import glob
import os.path
import shutil

source_dir = "./dumps/server1"
dest_dir = "./dedupmount"
tmpfile = "/tmp/delete.me"

for src_name in glob.glob(os.path.join(source_dir, '*.gz')):
    base = os.path.basename(src_name)
    dest_name = os.path.join(dest_dir, base[:-3])
    shutil.copyfile(src_name, tmpfile)
    with gzip.open(tmpfile, 'rb') as infile:
        with open(dest_name, 'wb') as outfile:
            for line in infile:
                outfile.write(line)

这将把源文件复制到本地机器上的临时文件tmpfile,然后从那里解压缩到目标文件。每次调用此脚本都会覆盖tmpfile

临时文件可能存在安全问题。为避免此问题,请将临时文件放置在一个只能被运行此脚本的用户所写入的目录中。


是的,但由于它通过管道提取,它将持续"传输"那个.gz文件从远程服务器直到它被解压缩,这需要很长时间并且涉及大量的I/O(除非我漏掉了什么)。这些文件非常庞大,我们希望尽可能减少对远程服务器的I/O,以防止性能影响和NFS挂载的"停滞"机会。这就是为什么我们有一个专门用于将.gz文件解压缩到其快速本地RAID0阵列驱动器的"专用"服务器。直接从远程服务器解压缩将会产生太大的负载,我猜想。 - bflance
这是设计计划:https://dl.dropboxusercontent.com/u/38751572/dedup-design.png - bflance
@bflance 尽管这不会改变服务器1的总IO,但三步计划足够简单:请参见更新的答案。 - John1024
我得到了这个错误:File "decompress_gz.py",第24行,在<module>中 outfile.write(line) TypeError: write()的参数必须是str,而不是bytes。 - BhishanPoudel
@BhishanPoudel 好的。看起来你正在使用Python3。我已经更新了代码,使用open(dest_name, 'wb'),这样它也可以在Python3中工作。 - John1024
显示剩余2条评论

0
你可以使用模块 urlopen
import urllib
#urlretrieve will save the file to local drive
urllib.urlretrieve(url,file_name_to_save)

现在你可以使用gunzip工具来解压缩,使用os.system函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接