2010-08-28 28 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

相關問題