Чтобы подсчитать количество членов архива в почтовый индекс архив в Python:
#!/usr/bin/env python
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
модули, если имеется, распаковать архив.
Для подсчета количества обычных файлов в архиве дегтя:
#!/usr/bin/env python
import sys
import tarfile
with tarfile.open(sys.argv[1]) as archive:
count = sum(1 for member in archive if member.isreg())
print(count)
Он может поддерживать gzip
, bz2
и lzma
сжатие в зависимости от версии Python.
Вы можете найти сторонний модуль, который обеспечит аналогичную функциональность для архивов 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:'): # found 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)
Он поддерживает неограниченный выход.
Could you explain why buffsize=-1 (as opposed to buffsize=1 in your previous answer: stackoverflow.com/a/30984882/281545)
bufsize=-1
означает использование по умолчанию I/O размер буфера вместо bufsize=0
(небуферизован) на Python 2. Это является повышение производительности на Python 2. Это по умолчанию в последних версиях Python 3. Вы можете получить короткое чтение (потерять данные), если на некоторых более ранних версиях Python 3, где bufsize
не изменен на bufsize=-1
.
Этот ответ читается в кусках, и поэтому поток полностью забуферирован для эффективности. The solution you've linked - ориентирован на линию. bufsize=1
означает «строка буферизирована». В противном случае существует минимальная разница с bufsize=-1
.
and also what the read_chunk = partial(p.stdout.read, 1 << 15) buys us ?
Это эквивалентно read_chunk = lambda: p.stdout.read(1<<15)
, но обеспечивает более интроспекцию в целом. Используется для implement wc -l
in Python efficiently.
Какой тип архива вы предполагаете поддержка? –
Для zip, tar проверьте https://docs.python.org/2/library/zipfile.html и https://docs.python.org/2/library/tarfile.html –
@ LoïcFaure-Lacroix: Спасибо - отредактирован. Мне определенно нужно 7z ... –