2

我正在使用reportlab将一些大型库(俄语纯文本)转换为 pdf 格式。当原始文件足够小(例如,大约 10-50 kB)时,它可以正常工作。但是,如果我尝试转换大文本(超过 500kB),reportlab 需要花费大量时间才能继续。有谁知道可能是什么问题?

BYTES_TO_READ = 10000 

def go(text):
    doc = SimpleDocTemplate("output.pdf")
    Story = [Spacer(1, 2*inch)]
    style = styles["Normal"]
    p = Paragraph(text, style)
    Story.append(p)
    doc.build(Story)

def get_text_from_file():
    source_file = open("book.txt", "r")
    text = source_file.read(BYTES_TO_READ)
    source_file.close()
    return text

go(get_text_from_file())

因此,当我尝试将BYTES_TO_READ变量设置为超过 200-30 万时(即,只是为了看看发生了什么,而不是阅读整本书,只是其中的一部分)——这需要大量的时间

4

1 回答 1

8

让我先说我在reportlab方面没有太多经验。这只是一个一般性建议。它也没有确切地处理你应该如何解析和格式化你正在阅读的文本到适当的结构。我只是继续使用Paragraph该类来编写文本。

在性能方面,我认为您的问题与尝试读取一个巨大的字符串并将该巨大的字符串作为单个段落传递给reportlab 有关。如果你想一想,什么段落是真正的 500k 字节?

您可能想要做的是以较小的块读取,并构建您的文档:

def go_chunked(limit=500000, chunk=4096):

    BYTES_TO_READ = chunk

    doc = SimpleDocTemplate("output.pdf")
    Story = [Spacer(1, 2*inch)]
    style = styles["Normal"]

    written = 0

    with open("book.txt", "r") as source_file:
        while written < limit:
            text = source_file.read(BYTES_TO_READ)
            if not text:
                break
            p = Paragraph(text, style)
            Story.append(p)
            written += BYTES_TO_READ

    doc.build(Story)

处理总共 500k 字节时:

%timeit go_chunked(limit=500000, chunk=4096)
1 loops, best of 3: 1.88 s per loop

%timeit go(get_text_from_file())
1 loops, best of 3: 64.1 s per loop

同样,显然这只是将您的文本分成任意段落,即 BYTES_TO_READ值的大小,但它与一个巨大的段落没有太大区别。最终,您可能希望将正在阅读的文本解析到缓冲区中,并确定您自己的段落,或者如果这是您原始源的格式,则只需按行拆分:

def go_lines(limit=500000):

    doc = SimpleDocTemplate("output.pdf")
    Story = [Spacer(1, 2*inch)]
    style = styles["Normal"]

    written = 0

    with open("book.txt", "r") as source_file:
        while written < limit:
            text = source_file.readline()
            if not text:
                break
            text = text.strip()
            p = Paragraph(text, style)
            Story.append(p)
            written += len(text)

    doc.build(Story)

表现:

%timeit go_lines()
1 loops, best of 3: 1.46 s per loop
于 2012-09-06T17:07:59.570 回答