Qthread cerrando Gui PySide

Estoy tratando de ejecutar un proceso en un subproceso separado pero está congelando mi Gui y no puedo entender por qué.

Estoy inicializando el hilo en la función init de mi clase:

self.cipher = Cipher() self.cipher_thread = QThread() self.cipher.moveToThread(self.cipher_thread) self.cipher_thread.started.connect(lambda: self.cipher.encrypt(self.plaintext_file_path, self.ciphertext_file_path, self.init_vector, self.key)) self.cipher_thread.start() 

El método de cifrado de la clase de cifrado es:

 def encrypt(self): # check that both the key and the initialisation vector are 16 bytes long if len(self.k) == self.key_byte_length and len(self.init_vector) == self.byte_length: if not self.used: self.used = True # get the padding bytes and store in a list self.padding_bytes = self.__getPaddingBytes() # generate sub keys # initial subkey is first four words from key init_subkey_words = [] for i in range(0, self.key_byte_length-3,4): init_subkey_words.append(self.k[i:i+4]) self.__genSubKeys(init_subkey_words) # read file and append the padding to it with open(self.plaintext_file_path, 'rb') as f: self.plaintext_data = bytearray(f.read()) self.plaintext_data += self.padding_bytes # set total size self.total_size_bytes = len(self.plaintext_data) # insert the initialisation vector as the first 16 bytes in the ciphertext data self.ciphertext_data = self.init_vector ''' begin encryption -------------------------------------------------------------------------------------------------------- ''' self.start_time = datetime.datetime.now() # loop through the file 16 bytes at a time for i in range(0, int(len(self.plaintext_data)), self.byte_length): # i increases by 16 each loop # if self.block_time is not None: # print('block time is', datetime.datetime.now()-self.block_time) self.block_time = datetime.datetime.now() # set the 16 byte state - bytearray Object state = copy.deepcopy(self.plaintext_data[i:i+self.byte_length]) # xor the state with the initialisation vector and first subkey for j in range(self.byte_length): state[j] ^= self.init_vector[j] state[j] ^= self.sub_keys[0][j] # round start # -------------------------------------------------------------------------------------------------- for j in range(self.num_rounds): self.current_round += 1 # increment current round counter ''' arrange the data into a 4x4 matrix [[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]] ''' state_matrix = np.array(state) state_matrix.resize(4, 4) state_matrix.swapaxes(0, 1) # byte substitution # ---------------------------------------------------------------------------------------------- for row in state_matrix: for byte in row: byte = self.__sBoxSubstitution(byte) # shift row - row k shifts left k places # ---------------------------------------------------------------------------------------------- state_matrix = state_matrix.tolist() for row in range(1, 4): for l in range(0, row): state_matrix[row].append(state_matrix[row].pop(0)) state_matrix = np.array(state_matrix) # mix column - not included in last round # ---------------------------------------------------------------------------------------------- if self.current_round is not self.num_rounds: # swap axes of state matrix state_matrix.swapaxes(0, 1) # create temporary holder for the computed values mixed_col_bytes = [[], [], [], []] for k in range(4): for l in range(4): mixed_col_bytes[k].append( self.__GFMult(self.MIX_COL_MATRIX[l][0], state_matrix[k][0]) ^ self.__GFMult(self.MIX_COL_MATRIX[l][1], state_matrix[k][1]) ^ self.__GFMult(self.MIX_COL_MATRIX[l][2], state_matrix[k][2]) ^ self.__GFMult(self.MIX_COL_MATRIX[l][3], state_matrix[k][3])) # restre state matrix from temporary holder and swap axes back state_matrix = np.array(copy.deepcopy(mixed_col_bytes)) state_matrix.swapaxes(0, 1) # restre single bytearray state state_matrix = state_matrix.flatten() state_matrix = state_matrix.tolist() state = bytearray(state_matrix) # key addition # ---------------------------------------------------------------------------------------------- for k in range(self.byte_length): state[k] ^= self.sub_keys[self.current_round][k] self.ciphertext_data += state # append state to ciphertext data self.init_vector = self.ciphertext_data[-16:] # update the initialisation vector self.current_round = 0 # reset current round number self.completed_size_bytes += self.byte_length self.percent_done = (self.completed_size_bytes/self.total_size_bytes)*100 self.updateProgressSig.emit(int(self.percent_done)) # finish encryption self.__saveEncryptedData() print('total encryption time:', datetime.datetime.now() - self.start_time) # finish self.finish(self.ciphertext_file_path) # either the key of the initialisation vector are not the correct length else: print(' either the key length or initialisation vector is the wrong length') print('---') print('key length:', len(self.k)) print('iv length:', len(self.init_vector)) 

El problema que está experimentando es que la función que se está conectando a la señal started no se ejecuta en el hilo, se ejecuta en el contexto de donde se estableció, que parece ser su hilo de interfaz de usuario.

Normalmente , querrá crear una clase personalizada que herede de QThread, y cualquier código que desee que se ejecute estará en la función run() de esa clase. Al igual que:

 class MyTask(QThread): def __init__ (self): QThread.__init__(self) def run(self): print("Code to run in the thread goes here.") 

Si eso parece una exageración, puedes establecer el valor de self.cipher_thread.run en tu propia función. Aquí hay un ejemplo:

 import time from PySide.QtCore import QThread from PySide import QtGui app = QtGui.QApplication("") def main(): task = SomeTask() thread = QThread() # Just some variables to pass into the task a, b, c = (1, 2, 3) thread.run = lambda: task.runTask(a, b, c) print("Starting thread") thread.start() # Doing this so the application does not exit while we wait for the thread to complete. while not thread.isFinished(): time.sleep(1) print("Thread complete") class SomeTask(): def runTask(self, a, b, c): print a, b, c print("runTask Started") time.sleep(5) print("runTask Complete") if __name__ == "__main__": main() 

Como Ekhumoro sugirió, estaba teniendo problemas con la GIL. Usar el módulo de multiprocesamiento me ha funcionado.