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〜300千を超える値に設定しようとすると(つまり、本全体を読むのではなく、本の一部だけを読むのではなく、何が起こっているのかを確認するためだけに)、非常に長い時間がかかります。

4

1 に答える 1

8

はじめに、reportlabの経験はあまりありません。これは単なる一般的な提案です。また、読んでいるテキストを適切な構造に解析およびフォーマットする方法についても正確に扱っていません。私はParagraphテキストを書くためにクラスを使い続けています。

パフォーマンスの観点から、あなたの問題は、巨大な文字列を1回読み取ろうとし、その巨大な文字列を1つの段落として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が、1つの大きな段落と大差ありません。最終的には、読み取っているテキストを解析してバッファーに入れ、独自の段落を決定するか、元のソースの形式である場合は行を分割することをお勧めします。

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 に答える