如何用Python创建一个关闭不当的gzip文件?
我有一个应用程序,有时候需要读取那些没有正确关闭的gzip文件。这些文件的表现是这样的:
>>> import gzip
>>> f = gzip.open("path/to/file.gz", 'rb')
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/gzip.py", line 292, in read
return self._buffer.read(size)
File "/usr/lib/python3.8/gzip.py", line 498, in read
raise EOFError("Compressed file ended before the "
EOFError: Compressed file ended before the end-of-stream marker was reached
我写了一个函数来处理这个问题,它是逐行读取文件,并捕捉EOFError
错误,现在我想测试一下这个函数。
我测试的输入应该是一个gz文件,它的表现和上面示例中的一样。我该如何在一个可控的测试环境中做到这一点呢?
我真的很不想复制那些在生产环境中得到的没有正确关闭的文件。
2 个回答
0
我并不想批评这个答案,因为它从技术上来说确实很好地回答了我提出的问题。
我还成功地创建了一个 gzip.GzipFile
的模拟对象,它的行为正好符合我的预期。
% python3 -m pytest test.py
============================================================= test session starts =============================================================
platform darwin -- Python 3.12.2, pytest-8.1.1, pluggy-1.4.0
rootdir: /private/tmp
collected 1 item
test.py . [100%]
============================================================== 1 passed in 0.03s ==============================================================
% cat test.py
from unittest import mock
import gzip
import pytest
def test_foo():
f = mock.Mock(gzip.GzipFile)
f.readline = mock.Mock(side_effect=["hello", EOFError()])
assert f.readline() == "hello"
with pytest.raises(EOFError):
f.readline()
我觉得为了单元测试,这可能是个更干净的解决方案,而不是实际创建文件并读取它,因为我可以简单地模拟打开文件的函数,让它返回我模拟的文件。
2
非常简单:先进行压缩,然后剪切结果。
import gzip
plain = b"Stuff"
compressed = gzip.compress(plain)
bad_compressed = compressed[:-1]
gzip.decompress(bad_compressed) # EOFError
更简单的是,只有两个字节就足够让gzip
模块识别gzip格式,但这显然不是一个完整的压缩文件。
bad_compressed = b'\x1f\x8b'
gzip.decompress(bad_compressed) # EOFError
这里为了演示方便,都是在内存中操作;如果你对文件进行操作而不是字符串,效果也是一样的。例如:
echo Stuff | gzip | head -c 2 >file.gz