Python script, чтобы объединить все файлы в каталоге в один файл
Я написал следующий script, чтобы объединить все файлы в каталоге в один файл.
Можно ли это оптимизировать с точки зрения
Вот фрагмент:
import time, glob
outfilename = 'all_' + str((int(time.time()))) + ".txt"
filenames = glob.glob('*.txt')
with open(outfilename, 'wb') as outfile:
for fname in filenames:
with open(fname, 'r') as readfile:
infile = readfile.read()
for line in infile:
outfile.write(line)
outfile.write("\n\n")
Ответы
Ответ 1
Используйте shutil.copyfileobj
для копирования данных:
import shutil
with open(outfilename, 'wb') as outfile:
for filename in glob.glob('*.txt'):
if filename == outfilename:
# don't want to copy the output into the output
continue
with open(filename, 'rb') as readfile:
shutil.copyfileobj(readfile, outfile)
shutil
читает из объекта readfile
в кусках, записывая их непосредственно в файл файл outfile
. Не используйте readline()
или итерационный буфер, так как вам не нужны накладные расходы на поиск окончаний строк.
Использовать тот же режим для чтения и записи; это особенно важно при использовании Python 3; Я использовал двоичный режим для обоих.
Ответ 2
Используя Python 2.7, я проверил некоторые "тесты"
outfile.write(infile.read())
против
shutil.copyfileobj(readfile, outfile)
Я повторил более 20 файлов .txt размером от 63 МБ до 313 МБ с общим размером файла ~ 2,6 ГБ. В обоих методах нормальный режим чтения выполнялся лучше, чем двоичный режим чтения, а shutil.copyfileobj был обычно быстрее, чем outfile.write.
При сравнении наихудшей комбинации (outfile.write, двоичный режим) с наилучшей комбинацией (shutil.copyfileobj, нормальный режим чтения) разница была довольно значительной:
outfile.write, binary mode: 43 seconds, on average.
shutil.copyfileobj, normal mode: 27 seconds, on average.
Исходный файл имел окончательный размер 2620 МБ в режиме нормального чтения и 2578 МБ в режиме двоичного чтения.
Ответ 3
Не нужно использовать много переменных.
with open(outfilename, 'w') as outfile:
for fname in filenames:
with open(fname, 'r') as readfile:
outfile.write(readfile.read() + "\n\n")
Ответ 4
Модуль fileinput обеспечивает естественный способ перебора нескольких файлов
for line in fileinput.input(glob.glob("*.txt")):
outfile.write(line)
Ответ 5
Мне было любопытно узнать больше о производительности, и я использовал ответы Мартина Питерса и Стивена Миллера.
Я пробовал двоичный и текстовый режимы с shutil
и без shutil
. Я попытался объединить 270 файлов.
Текстовый режим -
def using_shutil_text(outfilename):
with open(outfilename, 'w') as outfile:
for filename in glob.glob('*.txt'):
if filename == outfilename:
# don't want to copy the output into the output
continue
with open(filename, 'r') as readfile:
shutil.copyfileobj(readfile, outfile)
def without_shutil_text(outfilename):
with open(outfilename, 'w') as outfile:
for filename in glob.glob('*.txt'):
if filename == outfilename:
# don't want to copy the output into the output
continue
with open(filename, 'r') as readfile:
outfile.write(readfile.read())
Бинарный режим -
def using_shutil_text(outfilename):
with open(outfilename, 'wb') as outfile:
for filename in glob.glob('*.txt'):
if filename == outfilename:
# don't want to copy the output into the output
continue
with open(filename, 'rb') as readfile:
shutil.copyfileobj(readfile, outfile)
def without_shutil_text(outfilename):
with open(outfilename, 'wb') as outfile:
for filename in glob.glob('*.txt'):
if filename == outfilename:
# don't want to copy the output into the output
continue
with open(filename, 'rb') as readfile:
outfile.write(readfile.read())
Время работы в двоичном режиме -
Shutil - 20.161773920059204
Normal - 17.327500820159912
Время работы в текстовом режиме -
Shutil - 20.47757601737976
Normal - 13.718038082122803
Похоже, в обоих режимах shutil работает одинаково, а текстовый режим быстрее двоичного.
ОС: Mac OS 10.14 Мохаве. Macbook Air 2017.
Ответ 6
Вы можете напрямую перебирать строки файлового объекта, не читая все это в памяти:
with open(fname, 'r') as readfile:
for line in readfile:
outfile.write(line)