从内存中的字符串实例化Python类

0 投票
2 回答
599 浏览
提问于 2025-04-16 03:25

我正在使用Reportlab来创建PDF文件。我需要创建两个PDF文件,然后把它们合并在一起。Reportlab提供了一种方法,可以把一个pycanvas(其实就是我在内存中的PDF文件)保存为一个Python文件,然后调用这个Python文件里的doIt(filename)方法,就能重新生成PDF文件。这非常棒,因为这样我可以在源代码层面上把两个PDF合并成一个。

具体操作是这样的:

from reportlab.pdfgen import canvas, pycanvas
#create your canvas
p = pycanvas.Canvas(buffer,pagesize=PAGESIZE)
#...instantiate your pdf...

# after that, close the PDF object cleanly.
p.showPage()
p.save()

#now create the string equivalent of your canvas
source_code_equiv = str(p)
source_code_equiv2 = str(p)

#merge the two files on str. basis
#not shown how it is exactly done, to make it more easy to read the source
#actually one just have to take the middle part of source_code_equiv2 and add it into source_code_equiv
final_pdf = source_code_equiv_part1 + source_code_equiv2_center_part + source_code_equiv_part2

#write the source-code equivalent of the pdf
open("n2.py","w").write(final_pdf)
from myproject import n2
p = n2.doIt(buffer)

# Get the value of the StringIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response  

这个方法运行得很好,但我想跳过把n2.py保存到磁盘的这一步。因此,我在寻找一种方法,可以直接从final_pdf字符串实例化相应的Python类,并在源代码中直接使用它。这可能吗?

它应该像这样工作……

n2 = instantiate_python_class_from_source(final_pdf)
p = n2.doIt(buffer)

这样做的原因主要有两个:第一,实际上没有必要把源代码保存到磁盘;第二,这样做完全不安全。如果我在运行时给创建的文件命名,那我就不知道该导入什么了!如果没有办法避免保存文件,那有没有办法根据运行时定义的文件名来动态定义导入的内容呢?

有人可能会问,为什么我不提前创建一个PDF,但这是不可能的,因为它们来自不同的应用程序。

2 个回答

0

好的,我想你可以使用一个代码模块,它提供了标准解释器的交互模式。下面的代码会执行名为 doIt 的函数。

import code
import string
coded_data = """
def doIt():
    print "XXXXX"
"""
script = coded_data + "\ndoIt()\n" 
co = code.compile_command(script, "<stdin>", "exec")
if co:
    exec co

如果这对你有帮助,请告诉我。

1

这看起来是个很绕的方式来实现你想要的功能。Reportlab不是有一个Canvas类吗?你可以直接用它来生成PDF文档。我不明白为什么这里需要涉及到生成的Python源代码。

不过如果出于某种原因确实需要这样做,你可以使用StringIO来把源代码“写入”一个字符串,然后用exec来执行它:

from cStringIO import StringIO

source_code = StringIO()
source_code.write(final_pdf)
exec(source_code)
p = doIt(buffer)

撰写回答