在Python中计算zip归档文件中归档成员的数量:
import sys
from contextlib import closing
from zipfile import ZipFile
with closing(ZipFile(sys.argv[1])) as archive:
count = len(archive.infolist())
print(count)
如果可用的话,它可能会使用zlib
、bz2
、lzma
模块来解压缩存档。
要计算tar存档中常规文件的数量:
import sys
import tarfile
with tarfile.open(sys.argv[1]) as archive:
count = sum(1 for member in archive if member.isreg())
print(count)
根据Python版本的不同,它可能支持gzip
、bz2
和lzma
压缩。
您可以找到第三方模块来提供类似于7z归档的功能。
使用7z
工具获取存档文件中的文件数:
import os
import subprocess
def count_files_7z(archive):
s = subprocess.check_output(["7z", "l", archive], env=dict(os.environ, LC_ALL="C"))
return int(re.search(br'(\d+)\s+files,\s+\d+\s+folders$', s).group(1))
以下是一个版本,如果存档中有很多文件,可能会使用更少的内存:
import os
import re
from subprocess import Popen, PIPE, CalledProcessError
def count_files_7z(archive):
command = ["7z", "l", archive]
p = Popen(command, stdout=PIPE, bufsize=1, env=dict(os.environ, LC_ALL="C"))
with p.stdout:
for line in p.stdout:
if line.startswith(b'Error:'):
error = line + b"".join(p.stdout)
raise CalledProcessError(p.wait(), command, error)
returncode = p.wait()
assert returncode == 0
return int(re.search(br'(\d+)\s+files,\s+\d+\s+folders', line).group(1))
例子:
import sys
try:
print(count_files_7z(sys.argv[1]))
except CalledProcessError as e:
getattr(sys.stderr, 'buffer', sys.stderr).write(e.output)
sys.exit(e.returncode)
为了计算通用子进程输出中的行数:
from functools import partial
from subprocess import Popen, PIPE, CalledProcessError
p = Popen(command, stdout=PIPE, bufsize=-1)
with p.stdout:
read_chunk = partial(p.stdout.read, 1 << 15)
count = sum(chunk.count(b'\n') for chunk in iter(read_chunk, b''))
if p.wait() != 0:
raise CalledProcessError(p.returncode, command)
print(count)
它支持无限的输出。
你可以解释一下为什么buffsize = -1(而不是在您以前的答案stackoverflow.com/a/30984882/281545中为buffsize = 1)吗?
bufsize = -1
意味着在Python 2上使用默认的I/O缓冲区大小,而不是bufsize = 0
(无缓冲)。它是Python 2上的性能提升。它是最近的Python 3版本的默认值。如果将bufsize
未更改为bufsize = -1
,则可能会出现短读取(丢失数据)的情况,这在一些早期的Python 3版本中是存在的。
此答案分块读取数据,因此流完全缓冲以提高效率。您链接的解决方案 是面向行的,bufsize = 1
意味着它是“行缓冲”。否则与bufsize = -1
相比几乎没有区别。
那么,read_chunk = partial(p.stdout.read, 1 << 15)
对我们来说有什么作用?
它相当于 read_chunk = lambda: p.stdout.read(1<<15)
,但通常提供更多的内省信息。它用于有效实现Python中的“wc -l”。