Python 3.7 - Быстрый способ объединения строк и записи их на диск - PullRequest
2 голосов
/ 19 февраля 2020

Есть ли лучшая реализация для:

file = open("./myFile.txt","w+")
for doc in allDocuments: #around 35 million documents
    file.write(str(doc.number)+"\r\n")
f.close()

В настоящее время эта реализация принимает 20se c на файл

Ответы [ 2 ]

3 голосов
/ 19 февраля 2020

Ввод-вывод на самом деле не проблема, и вы ничего не можете с этим поделать: файловый объект и операционная система будут выполнять некоторую форму буферизации. Что вы можете сделать, так это количество вызовов методов, которые вы делаете.

with open("./myFile.txt", "w", newline='\r\n') as f:
    f.writelines(f'{doc.number}\n' for doc in allDocuments)

Метод writelines принимает итерируемую строку для записи в файл. (Документация говорит "список", но, похоже, речь идет о списках, а не list s; кажется, что выражение генератора тоже работает.) Выражение генератора создает каждую строку по запросу для writelines.


Вот тест:

import random

def allDocuments():
    for i in range(35_000_000):
        yield random.randint(0, 100)

with open("tmp.txt", "w", newline='\r\n') as f:
    f.writelines(f'{doc}\n' for doc in allDocuments())

Он завершился за 75 секунд (большая часть из-за повторных вызовов random.randint), используя менее 6 МБ памяти , (Замена вызова на random.randint на постоянное значение сократила время выполнения до 30 секунд.)

1 голос
/ 19 февраля 2020

Вы можете буферизовать вывод и записать в блоки:

with open("./myFile.txt", "w") as output:
    lines = []
    for doc in allDocuments:
        lines.append(f"{doc.number}\r\n")
        if len(lines) > 1000:
            output.writelines(lines)
            lines = []
    output.writelines(lines)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...