Skip to main content
 首页 » 编程设计

python之Qthread 锁定 Gui PySide

2025年05月04日32shihaiming

我试图在一个单独的线程中运行一个进程,但它卡住了我的 Gui,我不明白为什么。

我正在我类的 init 函数中初始化线程:

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() 

密码类的加密方式为:

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])) 
 
                        # restore state matrix from temporary holder and swap axes back 
                        state_matrix = np.array(copy.deepcopy(mixed_col_bytes)) 
                        state_matrix.swapaxes(0, 1) 
 
                    # restore 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)) 

请您参考如下方法:

您遇到的问题是您连接到 started 信号的函数未在线程中运行,它在设置它的上下文中运行,这似乎是您的 UI线程。

通常您会想要创建一个继承自 QThread 的自定义类,并且您想要执行的任何代码都将位于该类的 run() 函数中类(class)。像这样:

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

如果这看起来有点矫枉过正,您可以将 self.cipher_thread.run 的值设置为您自己的函数。这是一个例子:

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()