Reportlab Platypus 在第二次生成空文件
最简单的例子:
import io
import lorem
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph
styles = getSampleStyleSheet()
story = [Paragraph(lorem.text(), styles["Normal"])]
with io.BytesIO() as out:
doc = SimpleDocTemplate(out)
doc.build(story) # here, you can replace story with story[:] to fix it
with open("test.pdf", "wb+") as out:
doc = SimpleDocTemplate(out)
doc.build(story[:])
上面的代码生成一个空的PDF文件(960字节,没有内容,白色的空页)。如果在第一个 (BytesIO
) 块中将 build(story)
替换为 build(story[:])
,则 test .pdf
文件在第二个(open
文件)块中正确生成。
为什么?
(Windows 上的 Python 3.9.0 amd64,reportlab 3.5.65)
Minimal example:
import io
import lorem
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph
styles = getSampleStyleSheet()
story = [Paragraph(lorem.text(), styles["Normal"])]
with io.BytesIO() as out:
doc = SimpleDocTemplate(out)
doc.build(story) # here, you can replace story with story[:] to fix it
with open("test.pdf", "wb+") as out:
doc = SimpleDocTemplate(out)
doc.build(story[:])
The above code generates an empty PDF file (960 bytes, no content, white empty page). If you replace build(story)
with build(story[:])
in the first (BytesIO
) block, then the test.pdf
file is generated correctly in the second (open
file) block.
Why?
(Python 3.9.0 amd64 on Windows, reportlab 3.5.65)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
答案是故事被 doc.build 消耗。当您构建文档时,故事中的内部对象会发生更改,并且它们不能重复用于构建另一个文档。我认为它没有记录在任何地方。使用浅拷贝是不够的,它很可能最终会出现 reportlab.platypus.doctemplate.LayoutError 错误“Flowable 太大”。
当您想要多次渲染故事时,最安全的解决方案是始终使用深层副本:
The answer is that the story is consumed by doc.build. When you build a document, then the internal objects are changed inside your story, and they cannot be reused for bulding another document. I think it is not documented anywhere. Using a shallow copy is not enough, it will most likely end up in a reportlab.platypus.doctemplate.LayoutError error "Flowable too large".
The safest solution is to always use a deep copy, when you want to render a story multiple times: