Frage zu multiprocessing

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
dasKnödelchen
User
Beiträge: 4
Registriert: Montag 16. Juni 2014, 07:05

Hallo Python-Forum,

die letzten Tage hab ich mich mit dem multiprocessing-Modul auseinander gesetzt. Leider treten bei mir immer wieder Probleme auf. Um das ganze etwas zu üben, hab ich mir ein kleines Projekt überlegt. Mit einer PyQt-Oberfläche wähle ich einen Ordner aus in dem Textdateien liegen. Ich lade all Textdateien und übergebe sie an den Pool. Anschließend speichere ich den Text aller Dateien in einer Datei. Leider bekomme ich beim Drücken auf den "Combine Files"-Button die Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python34\lib\multiprocessing\process.py", line 254, in _bootstrap
    self.run()
  File "C:\Python34\lib\multiprocessing\process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Python34\lib\multiprocessing\pool.py", line 107, in worker
    task = get()
  File "C:\Python34\lib\multiprocessing\queues.py", line 357, in get
    return ForkingPickler.loads(res)
RuntimeError: super-class __init__() of type Form was never called
Code:

Code: Alles auswählen

from multiprocessing import Pool
import sys,glob
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QWidget, QPushButton, QListWidget, QFileDialog, QLineEdit

class Form(QWidget):
    def __init__(self):
        super(Form,self).__init__()
        self.resize(400,100)
        self.setWindowTitle("Combine Directory Files")
        
        self.btnDirectory = QPushButton("Select Directory...",self)
        self.btnDirectory.move(10,25)
        self.btnDirectory.clicked.connect(self.openDirectoryDialog)
        
        self.btnCombine = QPushButton("Combine Files", self)
        self.btnCombine.move(315,25)
        self.btnCombine.clicked.connect(self.combineFiles)
        
        self.txtDirectory = QLineEdit(self)
        self.txtDirectory.move(115,25)
        self.txtDirectory.resize(200,23)
        self.txtDirectory.setDisabled(True)
        
    def openDirectoryDialog(self):
        self.directory = QFileDialog.getExistingDirectory(self,"Select Directory", "C:\\Users\\std\\Desktop")
        self.txtDirectory.setText(self.directory) #write selected directory to textfield
        
    def getFilenames(self,directory):
        return glob.glob(directory + "\\*") #get all Files from directory as array
    
    def getFileContent(self, filepath):
        return open(filepath,"r") #return file content
    
    def saveFile(self, content, filepath):
        a = open(filepath + "\\combinedFiles.txt","w")
        a.write(content)
        a.close()
    
    def combineFiles(self):
        if(len(self.directory) > 0): #if user selected a directory
            content = ""
            filenames = self.getFilenames(self.directory)
            
            pool = Pool()
            filecontent = pool.map(self.getFileContent,filenames)
            pool.close()
            pool.join()
            content+=filecontent
            
            self.saveFile(content,"C:\\Users\\std\\Desktop")

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    
    form = Form()
    form.show()
    
    sys.exit(app.exec_())
Ich dachte eigentlich, mit:

Code: Alles auswählen

super(Form,self).__init__()
würde ich den Superklassen-Konstruktor schon ansprechen?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@dasKnödelchen: QT kann man nicht zusammen mit multiprocessing benutzen. `getFilenames`, `getFileContent` und `saveFile` haben in der Klasse auch gar nicht zu suchen, weil sie unabhängig von der `Form` sind. `getFileContent` hat einen falschen Namen, weil es ein File-Handle liefert, das übrigens auch nicht über multiprocessing ausgetauscht werden kann. Alles in allem ist die Aufgabe sowieso nicht für `multiprocessing` geeignet, weil wenig gerechnet wird, dafür aber um so mehr Daten transferiert werden müssen. Bevor Du etwas mit multiprocessing parallelisierst sollte es ohne schon funktionieren.

Um Dateipfade zusammenzusetzen nimmt man `os.path.join` und nicht String-Addition. Das `if` lässt sich kürzer und klarer schreiben als `if self.directory:`. Alle Attribute, insbesondere `self.directory`, sollten schon in der `__init__`-Methode mit Werten (zumindest mit None) befüllt werden.
dasKnödelchen
User
Beiträge: 4
Registriert: Montag 16. Juni 2014, 07:05

Danke für deine Antwort!
Nachdem ich deine Vorschläge bzw. Punkte umgesetzt hab, geht auf einmal alles :)
Antworten