Создание PDF отчета с использованием дублирующего текста на Python - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь автоматизировать создание PDF-файлов, читая данные из фрейма данных Pandas и записывая страницу в существующую PDF-форму, используя pyPDF2 и reportlab.Основное содержание программы здесь:

def pdfOperations(row, bp):
    packet = io.BytesIO()
    can = canvas.Canvas(packet, pagesize=letter)
    createText(row, can)
    packet.seek(0)
    new_pdf = PdfFileReader(packet)
    textPage = new_pdf.getPage(0)
    secondPage = bp.getPage(1)
    secondPage.mergePage(textPage)
    assemblePDF(frontPage, secondPage, row)
    del packet, can, new_pdf, textPage, secondPage

def main():
    df = openData()
    bp = readPDF()
    frontPage = bp.getPage(0)
    for ind in df.index:
        row = df.loc[ind]
        pdfOperations(row, bp)

Это отлично работает для первой строки данных и первого сгенерированного PDF, но для последующих весь текст перезаписывается.Т.е. второй pdf содержит текст из первой итерации и второй.Я думал, что сборка мусора позаботится обо всех изменениях памяти, но, похоже, этого не происходит.Кто-нибудь знает почему?

Я даже пытаюсь принудительно удалить объекты после того, как функция заработала, но не повезло ...

1 Ответ

0 голосов
/ 24 мая 2018

Вы читаете bp только один раз перед циклом. Затем в цикле вы получаете его вторую страницу через getPage(1) и объединяете вещи с ней. Но так как он всегда из одного и того же объекта (bp), каждая итерация будет сливаться с одной и той же страницей, поэтому все объединения, выполненные перед сложением.

Хотя я не нахожу никакого способа создания «глубокой копии» страницы в документах PyPDF2, он должен просто создать новый объект bp для каждой итерации.

Где-то в readPDF вы, должно быть, что-то сделали, когда открыли шаблон PDF в двоичный поток и затем передали его в PdfFileReader. Вместо этого вы можете прочитать данные в переменную:

with open(filename, "rb") as f:
    bp_bin = f.read()

И после этого создайте новый экземпляр PdfFileReader для каждой итерации цикла:

for ind in df.index:
    row = df.loc[ind]
    bp = PdfFileReader(bp_bin)
    pdfOperations(row, bp)

Это должно «сбрасывать» secondPage каждый раз без каких-либо дополнительных затрат на ввод / вывод файла. Каждый раз выполняется только синтаксический анализ, но в зависимости от размера и содержимого файла, может быть, это занимает мало времени, и вы можете с этим смириться.

...