用多线程处理界面没有响应的问题

  上一章节,我们用wxPython给图片格式转换器写了一个简单的GUI,测试时用的是几百张小图片,我们再来测试一下批量处理照片,照片的文件比较大,每张都有好几M。

  果真出问题了,界面卡死了。目标文件夹有新的图片还在不断生成,说明程序仍在运行,但是界面已经卡死。在处理复杂的任务的时候,不能把任务写在UI线程里,需要单独使用线程处理。代码修改如下:

# 点击转换格式按钮,触发此方法,获取图片输入输出路径和图片输出类型,转换图片。def ConvertButtonEvent(self, event):  srcPath = self.srcPathTextCtrl.GetValue() # 原图片路径  dstPath = self.dstPathTextCtrl.GetValue() # 目标图片路径  if srcPath == '':    wx.MessageBox('请选择图片输入路径', '消息', wx.OK | wx.ICON_INFORMATION)    return  if dstPath == '':    wx.MessageBox('请选择图片输出路径', '消息', wx.OK | wx.ICON_INFORMATION)    return  ext = self.extCombobox.GetValue() # 目标图片类型  # 用新线程执行处理图片的任务,并使用元组做为参数传入原图片路径、目标图片路径、目标图片类型  _thread.start_new_thread(self.process_image, (srcPath, dstPath, ext,))  # 处理图片def process_image(self, srcPath, dstPath, ext):  file_list = file_walk(srcPath)  for srcImagePath in file_list:    print(srcImagePath)    if os.path.getsize(srcImagePath) == 0:    continue    try:      image = Image.open(srcImagePath)      image = ImageOps.exif_transpose(image)      srcImageName = os.path.split(srcImagePath)[1]      dstImageName = os.path.splitext(srcImageName)[0] + ext      dstImagePath = os.path.join(dstPath, dstImageName)      image.save(dstImagePath)      self.tip.SetLabel('正在转换:%s' % srcImagePath)    except Exception as e:  print(e)self.tip.SetLabel('转换完成')

好了,界面不会卡死了,问题解决。

  但是感觉这个转换速度是真让人捉急!有什么好的办法让它能加快速度呢?对了,既然用了线程,为什么不用多线程来处理呢?继续修改代码

  # 用新线程执行处理图片的任务,并使用元组做为参数传入原图片路径、目标图片路径、目标图片类型  # _thread.start_new_thread(self.process_image, (srcPath, dstPath, ext,))  thread_pool = ThreadPoolExecutor(4)  file_list = file_walk(srcPath)  for srcImagePath in file_list:    # print(srcImagePath)    if os.path.getsize(srcImagePath) == 0:    continue    thread_pool.submit(self.process_image, srcImagePath, dstPath, ext)# 处理图片def process_image(self, srcImagePath, dstPath, ext):  print(srcImagePath)  try:    image = Image.open(srcImagePath)    image = ImageOps.exif_transpose(image)    srcImageName = os.path.split(srcImagePath)[1]    dstImageName = os.path.splitext(srcImageName)[0] + ext    dstImagePath = os.path.join(dstPath, dstImageName)    image.save(dstImagePath)    self.tip.SetLabel('正在转换:%s' % srcImagePath)except Exception as e:print(e)

这里用到了线程池

thread_pool = ThreadPoolExecutor(4)

  其中4代表线程池创建了4个线程,也就是说可以同时处理4张图片。那么是不是创建线程越多越好呢?其实并不是的,经过测试我发现处理线程数跟CPU的核心数有关,当创建的线程数越过CPU核心数时,速度也不会提升了。据说Python的多线程实际上并不能真正利用多核,所以如果使用多线程实际上还是在一个核上做并发处理。不过,如果使用多进程就可以真正利用多核,因为各进程之间是相互独立的,不共享资源,可以在不同的核上执行不同的进程,达到并行的效果。

  我们这里把线程数设置为CPU的核心数。到设备管理器和任务管理器里查看一下CPU的核心数

import osprint(os.cpu_count())

修改一下代码

thread_pool = ThreadPoolExecutor(max_workers=os.cpu_count())

现在是不是快多了!

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章