reportlab表现不佳

efi*_*efi 2 python pdf reportlab

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

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())
Run Code Online (Sandbox Code Playgroud)

因此,当我尝试将BYTES_TO_READ变量设置为超过200-300千(即,只是为了看看发生了什么,而不是阅读完整的书,只是它的一部分) - 需要花费大量的时间

jdi*_*jdi 7

让我先说一下我根本没有使用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)
Run Code Online (Sandbox Code Playgroud)

处理总共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
Run Code Online (Sandbox Code Playgroud)

再一次,显然这只是将你的文本分成任意段落,这些段落是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)
Run Code Online (Sandbox Code Playgroud)

性能:

%timeit go_lines()
1 loops, best of 3: 1.46 s per loop
Run Code Online (Sandbox Code Playgroud)