Vereinfachung gesucht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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

Code: Alles auswählen

dokument0.pdf
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

Code: Alles auswählen

if cores==1...
usw. irgendwie ungeschickt, auch wenn es funktioniert

Gruß Mathi
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

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.
Zuletzt geändert von Defnull am Montag 21. Dezember 2009, 14:36, insgesamt 1-mal geändert.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

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))
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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

Code: Alles auswählen

output.write(temp_file)
funktioniert nur, wenn alle relevaten .pdf gleichzeitig geöffnet sind
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

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
the more they change the more they stay the same
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Schau Dir mal contextlib.nested an.
MfG
HWK
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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 8)
Das hier ist das letzte Problemchen, dann habe ich mein Programm erstellt :-)


Gruß
Mathi
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

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
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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 :oops:
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@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
Zuletzt geändert von mathi am Dienstag 22. Dezember 2009, 08:12, insgesamt 1-mal geändert.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Ü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).
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@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 :-)
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

eine kurze frage habe ich noch,

warum ist das * in

Code: Alles auswählen

with nested(*(open(x, 'rb') for x in a)) as b:
notwendig, was wird damit bewirkt?? Dass es ohne nicht geht habe ich getestet.
Gruß
Mathi
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Der Modulo-Operator ist dein Freund.
Das Leben ist wie ein Tennisball.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

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 :oops:


edit: es funktioniert,wirklich peinlich....
Gruß Mathi
Antworten