Mik*_*ton 5 python gzip syslog
可能重复:
如何在不读取其全部内容的情况下拖尾压缩文件?
我有一个7GB的gzip syslog文件,提取到超过25GB.我需要只检索文件的第一行和最后一行,而不是一次将整个文件读入内存.
GzipFile()在Python 2.7中允许使用with读取头部(迭代通过with意味着我不必读取整个文件):
>>> from itertools import islice
>>> from gzip import GzipFile
>>> with GzipFile('firewall.4.gz') as file:
... head = list(islice(file, 1))
>>> head
['Oct 2 07:35:14 192.0.2.1 %ASA-6-305011: Built dynamic TCP translation
from INSIDE:192.0.2.40/51807 to OUTSIDE:10.18.61.38/2985\n']
Run Code Online (Sandbox Code Playgroud)
Python的2.6版本,以避免如问题AttributeError: GzipFile instance has no attribute '__exit__'(因为GzipFile中()不支持with迭代的GzipFile中())...
>>> from itertools import islice
>>> from gzip import GzipFile
>>> class GzipFileHack(GzipFile):
... def __enter__(self):
... return self
... def __exit__(self, type, value, tb):
... self.close()
>>> with GzipFileHack('firewall.4.gz') as file:
... head = list(islice(file, 1))
Run Code Online (Sandbox Code Playgroud)
这个问题是我无法检索尾部... islice()不支持负值,我找不到检索最后一行的方法而不迭代25GB文件(这需要太长时间).
在不将整个文件读入内存或迭代所有行的情况下读取gzip文本文件尾部的最有效方法是什么?如果无法做到这一点,请解释原因.
Mar*_*ler 13
gzip使用的deflate格式部分地通过在前面的32K数据中的某处找到匹配的字符串并使用对具有偏移量和长度的字符串的引用来压缩.因此,在任何时候从该点解压缩的能力取决于最后的32K,它本身取决于它之前的32K,依此类推回到开头.因此,要在流中的任何点x解压缩数据,您需要首先解压缩从0到x-1的所有内容.
有几种方法可以缓解这种情况.首先,如果您想要经常随机访问gzip文件,那么您将愿意完成扫描整个gzip文件并构建索引的工作.索引将在其中具有在某些入口点中的每一个处保存的先前32K,其中这些入口点的密度确定随机访问的速度.在zlib源代码分发中,您可以在examples/zran.c中看到此示例.
如果您控制gzip文件的生成,则可以使用Z_FULL_FLUSHflush选项定期擦除这些点上最后32K的历史记录,以允许随机访问.然后,您将保存这些点的位置作为索引,在每个入口点不需要32K历史块.如果这些点很少,那么对压缩的影响就会非常小.
Z_FULL_FLUSH只需编写连接的gzip流,你就可以通过编写gzip输出来实现类似的操作. gunzip将接受和解码与cat命令放在一起的gzip流,并将写出单个未压缩数据流.你可以用这种方式建立一个大的gzip日志,记住每个gzip片段开始的偏移量.
如果你只对尾部感兴趣,那么你可以在你的一条评论中做你的建议,即简单地在大gzip文件尾部的其他地方维护一个缓存.
我不知道你是否正在制作日志文件.如果是,您可能需要查看将有效的短日志消息附加到大型gzip文件的示例,该文件再次在zlib源代码分发中找到.
gzip文件是一个流,所以你必须通读它才能到达最后一行
from gzip import GzipFile
from collections import deque
dq = deque(maxlen=1)
with GzipFile('firewall.4.gz') as file:
head = next(file)
dq.extend(file)
tail = dq[0]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5239 次 |
| 最近记录: |