Seite 1 von 1
Vereinfachung gesucht
Verfasst: Montag 21. Dezember 2009, 14:20
von mathi
Für folgenden Schnipsel suche ich eine Vereinfachung,
wichtig ist, dass with open() weil die Dateien nach der Bearbeitung gelöscht werden sollen.
die Anzahl der Dateien
sind von der Größe von cores abhängig.
Das ganze sollte erweiterbar sein von cores=1 ... 8.
http://paste.pocoo.org/show/qMiEc9vrrlmcsO4IoEOQ/
Ich finde das mit
usw. irgendwie ungeschickt, auch wenn es funktioniert
Gruß Mathi
Verfasst: Montag 21. Dezember 2009, 14:36
von Defnull
Und da bist du nicht selbst drauf gekommen?
Code: Alles auswählen
for c in len(cores):
with open(self.tempdir+'\\document%d.pdf' % c, "rb") as doc:
pdf = PdfFileReader(doc)
for page in pdf.pages:
...
Das mit den cores wird dir aber nix bringen, wenn du nur einen Python Prozess startest.
Verfasst: Montag 21. Dezember 2009, 14:36
von jbs
Ungetestet:
Code: Alles auswählen
files = [os.path.join(self.tempdir, 'document{i}.pdf'.format(i=i)) for i in range(cores)]
pdfs = []
for f in files:
with open(f) as fobj:
pdfs.append(PdfFileReader(fobj))
Verfasst: Montag 21. Dezember 2009, 15:03
von mathi
Danke für Eure Antworten
@Defnull
wie kommst Du darauf, dass ich nur einen Prozess starte?
Jeder Prozess läuft auf einem CPU-Kern und liefert ein dokument_.pdf.
Deine Lösung funktioniert nicht, weil nur eine .pdf geöffnet wird.
Dass ich
Code: Alles auswählen
for nr in xrange(cores):
part=self.tempdir+'\\document%s.pdf' % nr
inputs.append(PdfFileReader(file(part, "rb")))
schreiben kann, weiß ich, bringt nur nix, weil die .pdf nach beenden des Programmes noch vom System geöffnet sind und nicht gelöscht werden können.
@jbs
Dein Vorschlag iteriert über files,
nach dem ersten Durchlauf wird die erste Datei aber wieder geschlossen

es müssen aber gleichzeitig alle .pdf geöffnet sein, damit der Rest funktionieren kann
funktioniert nur, wenn alle relevaten .pdf gleichzeitig geöffnet sind
Verfasst: Montag 21. Dezember 2009, 15:35
von Dav1d
mathi hat geschrieben:Code: Alles auswählen
for nr in xrange(cores):
part=self.tempdir+'\\document%s.pdf' % nr
inputs.append(PdfFileReader(file(part, "rb")))
schreiben kann, weiß ich, bringt nur nix, weil die .pdf nach beenden des Programmes noch vom System geöffnet sind und nicht gelöscht werden können.
Dann musst du die Datei in der For-Schleife öffnen und schließen, vorzugsweise "with" verwenden, ich seh da kein Problem, Defnull hats doch schon vorgemacht, wies gehen könnte/kann
Verfasst: Montag 21. Dezember 2009, 15:46
von HWK
Schau Dir mal contextlib.nested an.
MfG
HWK
Verfasst: Montag 21. Dezember 2009, 16:24
von mathi
vielleicht steh ich auf dem Schlauch, aber
jbs
hat ja schon nested() vorgeschlagen.
Der befehl ist meines Wissens nach nicht änderbar, ich meine damit:
Code: Alles auswählen
if cores==1:
with nested.....
elif cores==2:
with nested....
müßte ich dann schreiben, und genau dass wollte ich eben nicht...
@HWK
schau mal in meinen letzten Post unseres .pdf-Seitenzahlen-threads
Das hier ist das letzte Problemchen, dann habe ich mein Programm erstellt
Gruß
Mathi
Verfasst: Montag 21. Dezember 2009, 16:30
von HWK
mathi hat geschrieben:vielleicht steh ich auf dem Schlauch, aber
jbs
hat ja schon nested() vorgeschlagen.
Vielleicht steh ich auf dem Schlauch, aber wo denn?
Hier ein Beispiel, auf dem Du aufbauen kannst:
Code: Alles auswählen
>>> from contextlib import nested
>>> a = ['Test1', 'Test2']
>>> with nested(*(open(x, 'rb') for x in a)) as b:
print b
[<open file 'Test1', mode 'rb' at 0x018F91B0>, <open file 'Test2', mode 'rb' at 0x018F9430>]
MfG
HWK
Verfasst: Montag 21. Dezember 2009, 16:46
von mathi
HWK hat geschrieben:mathi hat geschrieben:vielleicht steh ich auf dem Schlauch, aber
jbs
hat ja schon nested() vorgeschlagen.
Vielleicht steh ich auf dem Schlauch, aber wo denn?
aaachh, hast recht, ich hatte seinen Vorschlag mit nested probiert und ihm das gleich mal angedichtet, Entschuldigung hast recht

Verfasst: Montag 21. Dezember 2009, 17:01
von mathi
@HWK
Mensch,
vielen Dank nochmal für Deine Geduld, jetzt hab ich es geschafft:
Code: Alles auswählen
for nr in xrange(cores):
pdfs.append(self.tempdir+'\\document%s.pdf' % nr)
with nested(*(open(x, 'rb') for x in pdfs)) as pdflist:
for x in pdflist:
file=PdfFileReader(x)
for page in file.pages:
output.addPage(page)
.........
output.write(temp_file)
@all
übrigens Danke an alle, mal gaanz pauschal
Gruß Mathi
Verfasst: Montag 21. Dezember 2009, 17:05
von Darii
Übrigens sollte man noch anmerken, dass solch naive Parallelisierung bei I/O-Zugriffen kontraproduktiv sein kann. Da I/O-Zugriffe meist sowieso nur seriell erfolgen kann das durchaus das ganze ausbremsen, wenn man trotzdem versucht 4 Dateien gleichzeitig zu lesen(dann langweilen sich nämlich alle 4 Prozessoren, während die 4 Dateien jeweils 4-Mal so langsam gelesen werden).
Verfasst: Montag 21. Dezember 2009, 17:14
von mathi
@Darii
siehe
http://www.python-forum.de/topic-21172,45.html
letzter Post,
parallelisiert werden ganz andere Sachen, das hier ist nur die Endverarbeitung des Ergebnisses, welche auf einem Kern läuft

Verfasst: Montag 21. Dezember 2009, 21:06
von mathi
eine kurze frage habe ich noch,
warum ist das * in
notwendig, was wird damit bewirkt?? Dass es ohne nicht geht habe ich getestet.
Gruß
Mathi
Verfasst: Montag 21. Dezember 2009, 21:30
von cofi
Verfasst: Dienstag 22. Dezember 2009, 16:10
von mathi
Danke,
ich habe noch einen Fehler entdeckt, bei dem ich um Hilfe Bitte:
Code: Alles auswählen
cores=cpu_count() # Anzahl der Kerne
teil=int(all_pages/cores) # Anzahl der Seiten, die je Kern zu bearbeiten sind
processes=[
Process(target=merge,
args=(teil,nr*teil,path,tempdir,nr))
for nr in xrange(cores)
]
das dumme ist, dass dbei dieser lösung ein Rest bleibt.
Bsp:
cores=4 # Anzahl der Kerne
all_pages=141
teil=int(all_pages/cores) = int(141/4)=35 # Anzahl der Seiten, die je Kern zu bearbeiten sind
macht bei 4 Kernen 4*35=140 Seiten
das heißt, ich müßte eigendlich so etwas machen:
Code: Alles auswählen
rest=all-(cores-1)*teil
first=(cores-1)*teil
kerne=cores-1
processes=[
Process(target=merge,
args=(teil,nr*teil,path,tempdir,nr))
for nr in xrange(kerne),
Process(target=merge,
args=(rest,first,path,tempdir,kerne))
]
So funktioniert es aber nicht.
Code: Alles auswählen
TypeError: unsupported operand type(s) for *: 'xrange' and 'int'
so funkktionierts natürlich für 4 Kerne:
Code: Alles auswählen
processes=[
Process(target=merge,
args=(teil,0*teil,path,tempdir,0)),
Process(target=merge,
args=(teil,1*teil,path,tempdir,1)),
Process(target=merge,
args=(teil,2*teil,path,tempdir,2)),
Process(target=merge,
args=(rest,3*teil,path,tempdir,3))
]
Könnt Ihr mir helfen??
Gruß Mathi
Verfasst: Dienstag 22. Dezember 2009, 17:06
von EyDu
Der Modulo-Operator ist dein Freund.
Verfasst: Dienstag 22. Dezember 2009, 19:06
von mathi
Danke,
mir ist eine einfache Lösung auf dem Heimweg eingefallen, die ich morgen gleichmal testen will:
Code: Alles auswählen
cores=cpu_count() # Anzahl der Kerne
teil=int(all_pages/cores) # Anzahl der Seiten, die je Kern zu bearbeiten sind
rest=all_pages-(cores-1)*teil)
liste=(teil,teil,teil,rest) # Beispiel für 4 Kerne, muß halt generiert werden
processes=[
Process(target=merge,
args=(liste[nr],nr*teil,path,tempdir,nr))
for nr in xrange(cores)
]
also falls das funktioniert, wäre es peinlich einfach
edit: es funktioniert,wirklich peinlich....
Gruß Mathi