vendredi 25 septembre 2015

Pyqt and general python, can this be considered a correct approach for coding?

I have a dialog window containing check-boxes, when each of them is checked a particular class needs to be instantiated and a run a a task on a separated thread (one for each check box). I have 14 check-boxes to check the .isChecked() property and is comprehensible checking the returned Boolean for each of them is not efficient and requires a lot more coding.

Hence I decided to get all the children items corresponding to check-box element, get just those that are checked, appending their names to list and loop through them matching their name to d dictionary which key is the name of the check box and the value is the corresponding class to instantiate.

EXAMPLE:

# class dictionary 

    self.summary_runnables = {'dupStreetCheckBox': [DupStreetDesc(),0],
                              'notStreetEsuCheckBox': [StreetsNoEsuDesc(),1],
                              'notType3CheckBox': [Type3Desc(False),2],
                              'incFootPathCheckBox': [Type3Desc(True),2],
                              'dupEsuRefCheckBox': [DupEsuRef(True),3],
                              'notEsuStreetCheckBox': [NoLinkEsuStreets(),4],
                              'invCrossRefCheckBox': [InvalidCrossReferences()],
                              'startEndCheckBox': [CheckStartEnd(tol=10),8],
                              'tinyEsuCheckBox': [CheckTinyEsus("esu",1)],
                              'notMaintReinsCheckBox': [CheckMaintReins()],
                              'asdStartEndCheckBox': [CheckAsdCoords()],
                              'notMaintPolysCheckBox': [MaintNoPoly(),16],
                              'notPolysMaintCheckBox': [PolyNoMaint()],
                              'tinyPolysCheckBox': [CheckTinyEsus("rd_poly",1)]}


# looping through list

    self.long_task = QThreadPool(None).globalInstance()
    self.long_task.setMaxThreadCount(1)
    for check_box_name in self.check_boxes_names:
        run_class = self.summary_runnables[check_box_name]
        # some signals I emit from my runnable
        run_class[0].signals.result.connect(self.log_progress)
        # running the task on a thread
        self.long_task.start(run_class[0])

Now, I used this approach before and it has always worked fine without using multiprocessing. In this case it works good to some extent, I can run the tasks the first time but if I try to run for the second time I get the following Python Error :

self.long_task.start(run_class[0])
RuntimeError: wrapped C/C++ object of type DupStreetDesc has been deleted

I tried to use run_class[0].setAutoDelete(False) before running them in the loop but pyQt crashes with a minidump error (I am running the code in QGIS) and I the programs exists with few chances to understand what has happened.

On the other hand, if I run my classes separately, checking with an if else statement each check-box, then it works fine, I can run the tasks again and the C++ classes are not deleted, but it isn't a nice coding approach, at least from my very little experience.

Is there anyone else out there who can advise a different approach in order to make this run smoothly without using too many lines of code? Or knows whether there is a more efficient pattern to handle this problem, which I think must be quite common?

Aucun commentaire:

Enregistrer un commentaire