社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

记一个有趣的 Python ZipInfo 的副作用

一个普普通通简简单单平平凡凡的神 • 8 年前 • 963 次点击  

0x00 前言

昨天修了一个有趣的 BUG,顺手分享出来。

本文目录

▼ 0x00 前言 : section
    本文目录 : section
▼ 0x01 场景 1 - 空文件打包问题 : section
▼ 0x02 场景 2 - zipinfo 带来的一个副作用 : section
▼ 0x03 处理 BUG 的一种姿势 : section
▼ 0xEE 结论 : section

0x01 场景 1 - 空文件打包问题

原始场景是这样的,在打包文件夹的时候,一切正常,但如果打包空文件夹的时候,就出问题了。

精简了这一段代码,当打包空文件夹的时候,大致逻辑如下

import zipfile

zfile = zipfile.ZipFile("tmp.zip",'w')
# 递归打包所有子文件
zfile.close()

这段代码很明显是造了一个空 zip 文件。

这个和我要的效果还不太一样。我要的是这个 zip 文件包含空目录 tmp/ 好,调整了一下代码。

import zipfile

zfile = zipfile.ZipFile("tmp.zip",'w')
zif = zipfile.ZipInfo("tmp/")
zfile.writestr(zif,"")
# 递归打包所有子文件
zfile.close()

嗯,现在下载成功了。解压缩也正常。

0x02 场景 2 - zipinfo 带来的一个副作用

显然,如果上面的东西皆大欢喜的结束了,我就没必要写这篇文章了。

问题来了,当我递归打包子文件的时候,文件会莫名其妙多了一个文件夹出来。

比如我打包文件夹 tmp,tmp 的内容如下

$ tree tmp
tmp
├── test.md

1 file

打包完毕多出了一个 tmp 文件夹

$ tree tmp
tmp
├── test.md
└── tmp

1 directory, 1 file

这种多出一个 tmp 的文件夹就是按照我这种方式使用 zipinfo 副作用。

WTF,怀着老鹿蹒跚的内心,打开了《伤心太平洋》:

一波还未平息
一波又来侵袭
茫茫人海 狂风暴雨

用代码复现一波场景

# 先造一个测试文件夹
mkdir /tmp/test_folder/
touch /tmp/test_folder/test.md

import zipfile
file_path = "/tmp/test_folder/test.md"
rel_name = "test.md"
zfile = zipfile.ZipFile("tmp.zip",'w')
zif = zipfile.ZipInfo("tmp/")
zfile.writestr(zif,"")
zfile.write(file_path, rel_name)
zfile.close()

0x03 处理 BUG 的一种姿势

  1. 场景能否描述出来 - 描述不出来的就没法准确定位问题
  2. 能否复现 - 复现不出来的 BUG 最难调试
  3. 业务问题还是技术问题 - 业务问题可能要和别人打交道,技术问题可能要多翻翻文档之类的。
  4. 时间是否来得及 - 如果时间来的及,就想办法弄懂,填坑;时间来不及就想办法规避,绕坑。

前三点自然不用说了,直接第四点,时间上还算充裕,

  1. 我翻了半天 zipfile 模块,并没有理解这个 BUG 的出现原因。
  2. 好,退后一步是人生,用代码规避掉这个问题。
import zipfile

if 是空文件夹:
    zfile = zipfile.ZipFile("tmp.zip",'w')
    zif = zipfile.ZipInfo("tmp/")
else 不是空文件夹:
    zfile.writestr(zif,"")
    zfile.write(file_path, rel_name)
zfile.close()

0xEE 结论

其实处理大部分的 BUG 基本上就是这么个思路:

  • 往前一步是黄昏:打破沙锅问到底的去探究,填坑
  • 退后一步是人生:没那么多时间搞明白细枝末节,用代码规避掉这个神奇 BUG,先让业务可以跑通,绕坑。

最后,欢迎关注我的知乎专栏,咱们聊聊我所知道的 Python / NodeJS/ Mac / DevOps 全栈(干)工程师的一些有趣的技术

MG的编程小屋 twocucao (twocucao)
今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/aMkwux78ci
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/20487