2010-08-28 49 views
0

我正在使用Reportlab创建PDF。我创建了两个我想在创建后合并的PDF。 Reportlab提供了一种方法来将pycanvas (source)(这基本上是我的pdf文件在内存中)保存为一个python文件,并调用该python文件的doIt(filename)方法将重新创建pdf文件。这很好,因为您可以在源代码基础上组合两个PDF并创建一个合并pdf。从类可用的字符串实例化python类,仅在内存中!

这是这样完成的:

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,但这是不可能的,因为它们来自不同的应用程序。

+0

是你真正提供了所需的最小码解释这个问题?这很长。 – allyourcode 2010-08-28 09:23:59

+0

现在应该会更好.. – 2010-08-28 09:38:25

回答

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) 
+0

嗯..只要调用doIt(buffer)将不起作用,因为doIt()是序列化pycanvas的一种方法。 – 2010-08-28 12:21:07

+0

我想我们需要看到这个生成的源代码样本,以了解正确的语法。如果你可以写入n2.py,然后导入n2,然后调用n2.doIt(),那么我的代码也应该工作。 – 2010-08-28 13:30:00

+0

我会三重检查你是否必须涉及生成Python代码。这看起来似乎有一个更简单的方法来做到这一点。 – 2010-08-28 13:30:43

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 

让我知道,如果这有帮助。

+0

谢谢,但我还不确定它是否有帮助;-)我需要将方法调用doIt(buffer)的返回值分配给p,就像我对此语句所做的那样:p = n2.doIt(缓冲区)..这可能吗? – 2010-08-28 09:57:55

相关问题