如何使用Python复制和提取.gz文件
我刚开始学习Python,有个问题想请教。
我想写个脚本来完成以下操作:(我会先用bash来说明我是怎么做的)
从远程服务器1复制一个
<file>.gz
文件到本地存储。cp /dumps/server1/file1.gz /local/
然后在本地解压这个文件。
gunzip /local/file1.gz
接着把解压后的文件复制到远程服务器2(用于归档和去重)。
cp /local/file1.dump /dedupmount
删除本地的.gz文件,以释放“临时”存储空间。
rm -rf /local/file1.gz
我需要对所有文件都执行这些操作。
所有的文件和目录都在同一台服务器上通过NFS挂载。
我会用一个for循环遍历/dump/
文件夹,寻找.gz
文件。
每个.gz
文件会先被复制到/local
目录,然后在那里解压。
解压后,得到的.dmp
文件会被复制到/dedupmount
文件夹进行归档。
我真是绞尽脑汁不知道该怎么写这个脚本。
2 个回答
你可以使用模块 urlopen
import urllib
#urlretrieve will save the file to local drive
urllib.urlretrieve(url,file_name_to_save)
现在你可以使用 gunzip 工具来解压,使用 os.system 命令。
Python 解决方案
虽然用命令行写的代码可能更短,但整个过程可以直接在 Python 中完成。Python 解决方案的关键点有:
使用
gzip
模块,gzipped 文件和普通文件一样容易读取。获取源文件列表时,使用
glob
模块。这个模块的设计灵感来自于命令行的 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 上完成的。
命令行代码
为了比较,这里是等效的命令行代码:
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
都会被覆盖。
临时文件可能会带来安全问题。为了避免这种情况,可以把临时文件放在一个只有运行这个脚本的用户可以写入的目录中。