简体   繁体   中英

Terminate a python thread that calls gdal functions

i have a program that uses gdal to process pictures. That is done in a thread that is started with a button click. Now, i need a way to terminate this thread at any given point, also with a button click. So i defined a function that i call when the button is clicked:

def terminateThread(self):
   self.change_button_caption.emit('Start')
   self.print_log.emit('Vorgang abgebrochen')
   self.show_progress.emit(0)
   self.terminate()

When i replace the actual code with a sleep order, this works. But it doesn't when the thread called a gdal function. How can i achieve the termination of this thread at any time?

this is the thread:

class MapThread(QThread):
    print_log = Signal(str)
    show_progress = Signal(int)
    change_button_caption = Signal(str)

    def __init__(self, path, tab_filelist, targetpath):
        QThread.__init__(self)
        self.path = path
        self.tab_filelist = tab_filelist
        self.targetpath = targetpath

    def run(self):
        self.change_button_caption.emit('Stop')
        print('MapThread run', flush=True)
        # try:
        from osgeo import gdal
        from osgeo import osr
        self.show_progress.emit(0)

        filename = self.tab_filelist[0].rsplit('\\', 1)[1].rsplit('.', 1)[0]
        path2 = self.targetpath + "\\" + filename + ".vrt"
        pathout = self.targetpath + "\\" + filename + ".mbtiles"

        d = gdal.Open(self.path)
        proj = osr.SpatialReference(wkt=d.GetProjection())
        self.print_log.emit('EPSG Code der Bilddaten: ' + proj.GetAttrValue('AUTHORITY', 1))
        # Vituelles Raster erzeugen
        vrt_options = gdal.BuildVRTOptions(resampleAlg='cubic', outputSRS=proj)
        gdal.BuildVRT(path2, self.tab_filelist, options=vrt_options)

        print('VRT Datei erzeugt', flush=True)
        self.print_log.emit('VRT Datei erzeugt')
        self.show_progress.emit(10)
        # mbtiles generieren
        creation_options = ["TILE_FORMAT=JPEG", "QUALITY=90"]
        
        src_ds = gdal.Open(path2)
        gdal.Translate(pathout, src_ds, format='mbtiles', creationOptions=creation_options)
        print('MB Tiles generiert', flush=True)
        self.print_log.emit('MB Tiles generiert')
        self.show_progress.emit(75)
        # Overviews erzeugen
        Image = gdal.Open(pathout, 1)
        gdal.SetConfigOption("COMPRESS_OVERVIEW", "DEFLATE")
        Image.BuildOverviews("AVERAGE", [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048])
        self.show_progress.emit(100)
        print('Overviews erfolgreich berechnet', flush=True)
        self.print_log.emit('Overviews erfolgreich berechnet')
        self.change_button_caption.emit('Start')
        # except Exception as err:
        #     print(err)

    def terminateThread(self):
        self.change_button_caption.emit('Start')
        self.print_log.emit('Vorgang abgebrochen')
        self.show_progress.emit(0)
        self.terminate()

and the functions for comunicating with the ui:

@Slot(str)
def printLog(self, msg):
    self.ui.list_status.addItem(msg)

@Slot(int)
def showProgress(self, value):
    self.ui.progressBar.setValue(value)

@Slot(str)
def changeCaption(self, txt):
    self.ui.btn_start_mbtiles.setText(txt)

Looks like gdal library is a binding - non-python code is called from python. So python's terminate() just can't stop it until execution returned to the python part. If you need to terminate your function immediatly, you may use processes instead of threads.

This may be helpful:

Is it possible to run function in a subprocess without threading or writing a separate file/script.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM