Skip to main content

压缩处理

zipfile

语法

with zipfile.ZipFile(output_name, "w") as z:
for each in file_list:
z.write(each, compress_type=zipfile.ZIP_DEFLATED)

注意:无论是py2还是py3,内置的zipfile模块在解压一些存在文件的zip文件时会出现乱码问题,解决方案是修正里面对中文decoe的处理

参数解析

  • compression

    • ZIP_STORED(no compression)
    • ZIP_DEFLATED(requires zlib)
    • ZIP_BZIP2(requires bz2)
    • ZIP_LZMA(requires lzma)
  • compresslevel

    • None (default for the given compression type) or an integer
    • specifying the level to pass to the compressor.
    • When using ZIP_STORED or ZIP_LZMA this keyword has no effect.
    • When using ZIP_DEFLATED integers 0 through 9 are accepted.
    • When using ZIP_BZIP2 integers 1 through 9 are accepted.

使用示例

def dir_to_zip(
file_dir: str,
*,
output_name: str = None,
file_list: list[str] = None,
exclude: list[str] = list(),
) -> str:
"""
传入一个目录,将该目录压缩成zip文件

- param file_dir :{str} 要压缩的目录
- param output_name :{str} 压缩后导出的位置(绝对路径)
- param file_list=None :{list[str]} 指定哪些文件需要压缩,默认该目录下所有文件
- param exclude :{list[str]} 要排除的目录或者文件

@returns `{str}` 如果成功返回压缩包名字,如果失败返回空""字符串
@example
```python
tar_dir = r'xxxx/'
res = dir_to_zip(tar_dir)

if not res: return print('压缩失败')
```
"""

res = ""
if not output_name:
name = os.path.basename(file_dir).split(".")[0]
output_name = os.path.join(file_dir, f"{name}.zip")

if not file_list:
file_list = os.listdir(file_dir)

cur_dir = os.getcwd()
base_dir = os.path.basename(file_dir)
try:
os.chdir(file_dir)
with zipfile.ZipFile(output_name, "w") as z:
for each in file_list:
if each in exclude:
continue
z.write(each, compress_type=zipfile.ZIP_DEFLATED)
res = output_name
except Exception as e:
print("z.write fail: ", e)

finally:
os.chdir(cur_dir)
return res
def pack_dir(target_dir, to_file):
target_dir_dir = os.path.dirname(target_dir)
dir_name = os.path.basename(target_dir)
cur_dir = os.getcwd()
to_file_name = os.path.basename(to_file)

# 手动打开文件句柄替换zipfile打开文件句柄
with open(to_file, "wb") as dest, zipfile.ZipFile(dest, "w", zipfile.ZIP_DEFLATED) as f:
for root_dir, dir_list, file_list in os.walk(target_dir):
for name in file_list:
target_file = os.path.join(root_dir, name)
arcname = target_file.replace(target_dir_dir, "") # 这里去掉绝对路径指定压缩包里面的文件所在目录结构
f.write(target_file, arcname=arcname)
return to_file

tarfile

shutil.make_archive

这是一个快速解包,打包的命令,功能相对固定,如果需要深度定制,可以使用zipfile模块

基础语法

shutil.make_archive(
base_name,
format[, root_dir[, base_dir, verbose, dry_run, owner, group, logger])

参数解释

  • base_name:压缩包的文件名,也可以是压缩包的路径;只是文件名时,则保存至当前目录下,否则保存至指定路径;
  • format:压缩包种类,“zip”, “tar”, “bztar”,“gztar”;
  • base_dir:指定要压缩文件的路径,可以指定路径下的文件名,也可以指定路径;
  • root_dir:指定要压缩的路径根目录(默认当前目录),只能指定路径,优先级低于base_dir。

使用示例

  • 错误示例

    把当前目录下的文件压缩生成copy.zip文件到当前目录下

import shutil
shutil.make_archives('copy','zip')

注意:此操作会出现递归拷贝压缩导致文件损坏(当前目录下的copy.zip中会有copy.zip)

import shutil
shutil.make_archives('D:\copy3\copy','zip',base_dir='D:\copy2\\测试.txt')

shutil.unpack_archive

import shutil
shutil.unpack_archive('xxxx.zip')

代码实例

rar、zip、tgz、tar、gz

def uncompress(src_file, dest_dir):
"""
@Description 解压各种类型的压缩包

- param src_file :{file|str} 你要解压的压缩包文件
- param dest_dir :{str} 你要解压到的目标路径

@returns `{str}` 成功返回压缩路径,失败返回空
@example
```python
src_file = 'xxx.zip'
dest_dir = '你要解压到的目标路径'

res = uncompress(src_file, dest_dir)
# or
with open('你要解压的压缩包文件路径', 'rb') as src_file:
res = uncompress(src_file, dest_dir)
"""

if isinstance(src_file, str):
with open("你要解压的压缩包文件路径", "rb") as f:
src_file = f

_, file_type = os.path.splitext(src_file.filename)

try:
if file_type == ".zip":
import zipfile # 需要安装zip包:pip install zipp

zip_file = zipfile.ZipFile(src_file)
for names in zip_file.namelist():
zip_file.extract(names, dest_dir)
zip_file.close()

return dest_dir

elif file_type == ".rar":
try:
import rarfile # 需要安装rar包:pip install rarfile

rar = rarfile.RarFile(src_file)
os.chdir(dest_dir)
rar.extractall()
rar.close()

return dest_dir
except Exception as err:
print("uncompress rar fail: ", err)
return ""

elif file_type == ".tgz" or file_type == ".tar" or file_type == ".gz":
import tarfile # Python自带tarfile模块

tar = tarfile.open(fileobj=src_file)
for name in tar.getnames():
tar.extract(name, dest_dir)
tar.close()

return dest_dir
else:
print("不支持的格式: {}".format(file_type))
return ""

except Exception as ex:
print("uncompress fail: ", ex)
return ""

使用

if name == 'main': dest_dir = '你要解压到的目标路径' with open('你要解压的压缩包文件路径', 'rb') as src_file: result = uncompress(src_file, dest_dir)