Seite 2 von 3
Verfasst: Samstag 5. Dezember 2009, 14:41
von HWK
Du brauchst nur einen Pool. Also 59 löschen, 60 und 61 ausrücken.
Da die zeitliche Reihenfolge der Aufrufe von 22 nicht unbedingt der Reihenfolge der Seiten entsprechen muss, sollte merge lieber page zurückliefern. Dann kannst Du das PDF-File aus der von pool.map erzeugten Liste generieren.
Und räume Deinen Code unbedingt etwas auf. Ich bin zwar kein PEP-8-Fanatiker, aber Deinen Code zu lesen, ist doch sehr anstrengend.
MfG
HWK
Verfasst: Samstag 5. Dezember 2009, 20:43
von mathi
Danke für Eure Hinweise,
hier stand dummes Zeug
Verfasst: Sonntag 6. Dezember 2009, 14:02
von mathi
ich habe den code mal ein bissel gestrafft, und soweit scheint das zusammenführen der .pdf Dateien auch zu funktionieren, leider erhalte ich eine korrupte Ergebnisdatei, woran kann das liegen??
(mir ist klar, dass es nicht gut ist input1 2-mal zu erzeugen unter main() und unter merge(), aber mir geht es erst einmal darum dass das programm funktioniert, danach möchte ich mich erst um solche Dinge kümmern)
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from pyPdf import PdfFileWriter, PdfFileReader
from tempfile import mkdtemp
from reportlab.pdfgen import canvas
from tempfile import NamedTemporaryFile
import os, multiprocessing
tempdir=mkdtemp(suffix='TemppP')
output = PdfFileWriter()
pagelist=[] # Liste zum zwischenparken der pages in merge()
def main():
input1 = PdfFileReader(file("test_lang.pdf", "rb"))
pages=input1.getNumPages()
pool = multiprocessing.Pool()
pool.map(merge,range(pages))
for page in pagelist:
output.addPage(page)
temp_file = NamedTemporaryFile(suffix = '.pdf', prefix = 'temp',delete=False,dir =tempdir)
output.write(temp_file)
os.startfile(temp_file.name)
temp_file.close()
def merge(pagenum):
input1 = PdfFileReader(file("test_lang.pdf", "rb")) #Orginaldatei
#with open ("temp.pdf", "rb") as (tmp_file):
watermark = PdfFileReader(file("temp.pdf", "rb")) # temp-Datei mit den Seitennummern muß die gleiche Seitenanzahl haben
page=input1.getPage(pagenum)
page.mergePage(watermark.getPage(pagenum))
pagelist.append(page)
if __name__ == "__main__":
main()
(Ich habe jetzt das generieren der .pdf ausgespart, wer es testen möchte brauch nur eine .pdf in "test_lang.pdf" umzubenennen und die gleiche oder eine mit der selben Anzahl an Seiten als "temp.pdf" zu bezeichnen..)
Verfasst: Sonntag 6. Dezember 2009, 16:56
von HWK
Warum verwendest Du in merge nicht wie vorgeschlagen
? pool.map liefert dann eine Liste der Seiten in der richtigen Reihenfolge. So ist die Reihenfolge der neuen Seiten nicht zwingend dieselbe wie die der alten.
MfG
HWK
Verfasst: Sonntag 6. Dezember 2009, 19:31
von mathi
werde ich machen, aber wie heißt denn die Liste, die return zurückgibt? Ich muß doch die einzelnen pages z.B. mit einer for-Schleife zum output hinzufügen, möglichst in der richtigen reihenfolge..
Vielen Dank für die geduld, die Ihr mit mir habt

Verfasst: Montag 7. Dezember 2009, 00:41
von ms4py
mathi hat geschrieben:werde ich machen, aber wie heißt denn die Liste, die return zurückgibt? Ich muß doch die einzelnen pages z.B. mit einer for-Schleife zum output hinzufügen, möglichst in der richtigen reihenfolge..
Vielen Dank für die geduld, die Ihr mit mir habt

pool.map liefert die Liste zurück! Ist doch aus der Doku echt offensichtlich, du musst doch eigentlich nur diese EINE Zeile nachvollziehen können, dann ist doch komplett klar, was die map Funktion macht und zurückgibt:
Code: Alles auswählen
print pool.map(f, range(10)) # prints "[0, 1, 4,..., 81]"
Verfasst: Montag 7. Dezember 2009, 08:39
von mathi
wenn das so einfach wäre, hätte ich nicht gefragt, denn mit
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from pyPdf import PdfFileWriter, PdfFileReader
from tempfile import mkdtemp
from reportlab.pdfgen import canvas
from tempfile import NamedTemporaryFile
import os, multiprocessing
#tempdir=mkdtemp(suffix='TemppP')
def main():
output = PdfFileWriter()
input1 = PdfFileReader(file("test_lang.pdf", "rb"))
pages=input1.getNumPages()
pool = multiprocessing.Pool()
pagelist=pool.map(merge,range(pages))
for page in pagelist:
output.addPage(page)
temp_file = NamedTemporaryFile(suffix = '.pdf', prefix = 'temp',delete=False)
output.write(temp_file)
os.startfile(temp_file.name)
temp_file.close()
def merge(pagenum):
input1 = PdfFileReader(file("test_lang.pdf", "rb")) #Orginaldatei
#with open ("temp.pdf", "rb") as (tmp_file):
watermark = PdfFileReader(file("temp.pdf", "rb"))
page=input1.getPage(pagenum)
page.mergePage(watermark.getPage(pagenum))
return page
if __name__ == "__main__":
main()
erhalte ich folgenden Fehler:
Code: Alles auswählen
Traceback (most recent call last):
File "D:\Python\Code\wxPython\workspace\pdfPage\src\pdfPageCMD1.py", line 35, in <module>
main()
File "D:\Python\Code\wxPython\workspace\pdfPage\src\pdfPageCMD1.py", line 22, in main
output.write(temp_file)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 237, in write
self._sweepIndirectReferences(externalReferenceMap, self._root)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 312, in _sweepIndirectReferences
self._sweepIndirectReferences(externMap, realdata)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 288, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, value)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 312, in _sweepIndirectReferences
self._sweepIndirectReferences(externMap, realdata)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 288, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, value)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 297, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, data[i])
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 312, in _sweepIndirectReferences
self._sweepIndirectReferences(externMap, realdata)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 288, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, value)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 288, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, value)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 288, in _sweepIndirectReferences
value = self._sweepIndirectReferences(externMap, value)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 318, in _sweepIndirectReferences
newobj = data.pdf.getObject(data)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 615, in getObject
self.stream.seek(start, 0)
ValueError: I/O operation on closed file
dieser tritt in org. Programm also ohne multiprocessing nicht auf. Das heißt doch, dass
entweder beim Erstellen der Liste in map() was schief läuft oder das ich nicht die richtigen Objekte an output übergebe, oder??
bedeutet doch, das der Startwert nicht stimmt??
Verfasst: Montag 7. Dezember 2009, 13:11
von mathi
mal abgesehen davon, dass es mit functools.partail und pool.map() generell probleme zu geben scheint (
http://mail.python.org/pipermail/python ... 86039.html) habe ich mal probiert das einzubauen(mit dem Umweg vgl. mailinglist):
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from pyPdf import PdfFileWriter, PdfFileReader
from tempfile import mkdtemp
from reportlab.pdfgen import canvas
from tempfile import NamedTemporaryFile
import os, multiprocessing,copy_reg, functools
#Beginn: making functools.partial picklable
def _reconstruct_partial(f, args, kwds):
return functools.partial(f, *args, **(kwds or {}))
def _reduce_partial(p):
return _reconstruct_partial, (p.func, p.args, p.keywords)
copy_reg.pickle(functools.partial, _reduce_partial)
#Ende: making functools.partial picklable
def main():
output = PdfFileWriter()
input1 = PdfFileReader(file("test_lang.pdf", "rb"))
watermark = PdfFileReader(file("temp.pdf", "rb"))
pages=input1.getNumPages()
merge2=functools.partial(merge,input1=input1,watermark=watermark) #<-- functools.partial
#for pagenum in range(pages): # so funktioniert es
# output.addPage(merge2(pagenum)) # so funktioniert es
pool = multiprocessing.Pool() # so geht's nicht
for page in pool.map(merge2,range(pages)): # so geht's nicht
output.addPage(page) # so geht's nicht
temp_file = NamedTemporaryFile(suffix = '.pdf', prefix = 'temp',delete=False)
output.write(temp_file)
os.startfile(temp_file.name)
temp_file.close()
def merge(pagenum,input1,watermark):
page=input1.getPage(pagenum)
page.mergePage(watermark.getPage(pagenum))
return page
if __name__ == "__main__":
main()
ich erhalte die Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "D:\Python\Code\wxPython\workspace\pdfPage\src\pdfPageCMD1.py", line 45, in <module>
main()
File "D:\Python\Code\wxPython\workspace\pdfPage\src\pdfPageCMD1.py", line 30, in main
pagelist=pool.map(merge2,range(pages))
File "C:\Python26\lib\multiprocessing\pool.py", line 148, in map
return self.map_async(func, iterable, chunksize).get()
File "C:\Python26\lib\multiprocessing\pool.py", line 422, in get
raise self._value
ValueError: I/O operation on closed file
habe ich partial falsch verwendet?? So wie ich das verstehe, übergebe ich genau die Werte (von links nach rechts) die ich in der Funktion merge() brauche und nicht in pool.map übergeben kann ???
Verfasst: Montag 7. Dezember 2009, 14:14
von HWK
Offensichtlich werden die Dateien zwischenzeitlich geschlossen. Lies doch die Seiten erst alle in eine Queue ein (vor pool.map) und hole Dir dann in merge die Seiten aus der Queue. Du musst dann natürlich auch die Seitennummer in der Queue speichern. Das Erstellen der Wassermarke könntest Du dann auch in merge erledigen.
MfG
HWK
Verfasst: Montag 7. Dezember 2009, 14:53
von mathi
es ist zum Mäusemelken:
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from pyPdf import PdfFileWriter, PdfFileReader
from tempfile import NamedTemporaryFile
from Queue import Queue
import os, multiprocessing
q_seiten = Queue()
q_zahlen=Queue()
def main():
output = PdfFileWriter()
input1 = PdfFileReader(file("test_lang.pdf", "rb"))
watermark = PdfFileReader(file("temp.pdf", "rb"))
pages=input1.getNumPages()
for pagenum in range(pages):
q_seiten.put(input1.getPage(pagenum))
q_zahlen.put(watermark.getPage(pagenum))
#for pagenum in range(pages): # so funktioniert es
# output.addPage(merge(pagenum)) # so funktioniert es
pool = multiprocessing.Pool() # so geht's nicht
for page in pool.map(merge,range(pages)): # so geht's nicht
output.addPage(page) # so geht's nicht
temp_file = NamedTemporaryFile(suffix = '.pdf', prefix = 'temp',delete=False)
output.write(temp_file)
os.startfile(temp_file.name)
temp_file.close()
def merge(pagenum):
#while True:
page=q_seiten.get()
page.mergePage(q_zahlen.get())
return page
q_seiten.task_done()
q_zahlen.task_done()
#q_zahlen.join()
if __name__ == "__main__":
main()
dieses pool.map bringt mich noch ins grab

,
zumindest könnte ich mit Queue die probleme mit functools.partial umgehen
ich hab testweise mal 2 Queue erstellt. Ohne multiprocessing funktioniert es wie es soll, aber mit pool.map startet die Iteration schon gar nicht

Verfasst: Dienstag 8. Dezember 2009, 10:41
von mathi
Da ich das Gefühl hatte, dass es it pool.map nix wird, habe ich mal versucht mit Process() weiterzukommen:
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from pyPdf import PdfFileWriter, PdfFileReader
from tempfile import NamedTemporaryFile
from multiprocessing import Process, Queue
import os
def merge1(q1s,q1z):
while True:
page=q1s.get()
page.mergePage(q1z.get())
q1a.put(page)
q1s.task_done()
q1z.task_done()
if __name__ == '__main__':
output = PdfFileWriter()
input1 = PdfFileReader(file("test_lang.pdf", "rb"))
watermark = PdfFileReader(file("temp.pdf", "rb"))
pages=input1.getNumPages()
q1s=Queue() #Seiten=input1
q1z=Queue() #Seitenzahlen = watermark
q1a=Queue() #Output
for i in xrange(pages):
q1s.put(input1.getPage(i))
q1z.put(watermark.getPage(i))
p1 = Process(target=merge1, args=(q1s,q1z))
p1.start()
p1.join()
while True:
page=q1a.get()
output.addPage(page)
temp_file = NamedTemporaryFile(suffix = '.pdf', prefix = 'temp',delete=False)
output.write(temp_file)
os.startfile(temp_file.name)
temp_file.close()
Ich haber erstmal nur einen Prozess, um zu sehen ob es funktioniert...die Fehlermeldung lautet:
Code: Alles auswählen
Process Process-1:
Traceback (most recent call last):
File "C:\Python26\lib\multiprocessing\process.py", line 232, in _bootstrap
self.run()
File "C:\Python26\lib\multiprocessing\process.py", line 88, in run
self._target(*self._args, **self._kwargs)
File "D:\Python\Code\wxPython\workspace\pdfPage\src\pdfPageCMD5a.py", line 12, in merge1
page.mergePage(q1z.get())
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 1095, in mergePage
self._mergePage(page2)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 1122, in _mergePage
new, newrename = PageObject._mergeResources(originalResources, page2Resources, res)
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 1030, in _mergeResources
page2Res = res2.get(resource, DictionaryObject()).getObject()
File "C:\Python26\lib\site-packages\pyPdf\generic.py", line 165, in getObject
return self.pdf.getObject(self).getObject()
File "C:\Python26\lib\site-packages\pyPdf\pdf.py", line 615, in getObject
self.stream.seek(start, 0)
ValueError: I/O operation on closed file
da ich aber sämtliche Seiten in je eine Queue gepackt habe, kann
HWK hat geschrieben:Offensichtlich werden die Dateien zwischenzeitlich geschlossen.
doch nicht stimmen...
Verfasst: Dienstag 8. Dezember 2009, 14:02
von HWK
page enthält wohl nicht den Seiteninhalt der pdf-Datei, sondern nur eine Referenz darauf. Der Inhalt muss also erst wieder aus der Datei ausgelesen werden, die aber offensichtlich schon wieder geschlossen wurde. Auch zum Schreiben der Ausgabe muss wohl die Eingabedatei geöffnet sein. Versuch doch mal statt
Code: Alles auswählen
with open('test_lang.pdf', 'rb') as infile:
input1 = PdfFileReader(infile)
um den GC am Schließen der datei zu hindern. Damit kannst Du ja mal Deine verscheidenen Varianten testen.
MfG
HWK
Verfasst: Dienstag 8. Dezember 2009, 14:19
von mathi
@HWK.
vielen Dank für Deine Geduld, ich bin froh, dass ich Hilfe bekomme
zusammengefasst kann man sagen, es ändert sich nichts
Hier mal die vielversprechendste Version:
http://paste.pocoo.org/show/XcyNU3ej5Bk8zEOVwqPb/
es werden 4 python.exe im Tastmanager angezeigt, es wird aber nichts gerechnet...
in der Version mit Process()
http://paste.pocoo.org/show/ruDIdmowrkJixVQqy1B0/
bleibt die Fehlermeldung.
Kann es sein, dass es an pypdf liegt??
Verfasst: Dienstag 8. Dezember 2009, 20:13
von HWK
Das wird zwar das Problem nicht lösen, aber neue vermeiden:
Du solltest nur eine Queue verwenden, in der Du Tuple aus der Seitennummer, der Originalseite und der "Partnerseite" speicherst, damit Du sicher sein kannst die richtigen Seiten zu verknüpfen und deren Seitennummer kennst. merge sollte ein Tuple aus Seitennummer und der fertigen Seiten zurückliefern. Zum Schluss solltest Du die Seiten in der Reihenfolge ihrer Seitennummer ausgeben.
Um den Fehler einzugrenzen, solltest Du ein paar informative Prints einbauen, z.B. in merge pagenum und page ausgeben lassen etc. Dann kann man weiter sehen.
Ich möchte wohl verständlicherweise meinen Rechner nicht mit Modulen "zuzumüllen", die ich ansonsten nicht brauche, um Deine Scripts zu testen.
MfG
HWK
Verfasst: Dienstag 8. Dezember 2009, 22:45
von mathi
so, ich habs mal so gemacht, wie vorgeschlagen (außer der Ergebnistupelausgabe)
hier mal dasergebnis:
http://paste.pocoo.org/show/jE9BOITC2OJWdtqX2cRk/
als singleprocess funktioniert es (natürlich),
aber es hängt beim start der pool.map, denn hier die Ausgabe:
es wird die Zeile
gar nicht erst ausgeführt, d.h. merge nicht ein einziges mal aufgerufen...
übrigens das auskommentierte
bringt einen timeout
Verfasst: Dienstag 8. Dezember 2009, 23:21
von HWK
ruft merge auch nicht auf?
MfG
HWK
Verfasst: Mittwoch 9. Dezember 2009, 08:02
von mathi
nein, bzw. wird das einfach übersprungen - ich bekomme zwar keinen Fehler, aber die print-Anweisungen in merge werden nicht ausgeführt...
das print des ergebnisses von pool.apply_async bringt dann den timeout (auch bei einem Wert von timeout=100)
Verfasst: Mittwoch 9. Dezember 2009, 12:26
von HWK
Schreib doch die "Print-Nachrichten" in merge einmal in eine Log-Datei.
MfG
HWK
Verfasst: Mittwoch 9. Dezember 2009, 14:14
von mathi
wir kommen der Sache näher...
Code: Alles auswählen
def merge(pagenum):
print "pagenum = %s" % pagenum
log=file('logfile%s.txt' % pagenum,'w')
log.write("pagenum = %s" % pagenum)
#log.close() #----- erzeugt txt. Dateien mit "pagenum= 7" usw.
pagelist=q.get()
log.write(pagelist)
log.close() #---- hier bleibt es hängen, d.h. q.get() macht Probleme
page=pagelist[1]
watermark=pagelist[2]
page.mergePage(watermark)
return page
q.task_done()
merge wird also doch aufgerufen, es entstehen 4 .txt Dateien (logfile0.txt, logfile7.txt, logfile14.txt, logfile21.txt) mit log.close() vor q.get() steht in den Dateien jeweils die Seitennummer, bei log.close() nach q.get() bleiben die Dateien leer...
(wobei es mich wundert, dass print
vor q.get() nicht ausgeführt wird)
Verfasst: Mittwoch 9. Dezember 2009, 15:11
von HWK
Noch eine Idee:
Übergib doch q mal merge als Argument. pagenum brauchst Du nicht als Argument. Die richtige Seitennummer steht ja in der Queue. q braucht dann auch nicht mehr global zu sein.
MfG
HWK