【问题标题】:How about using multiple threads/process to make programs run faster in python如何使用多个线程/进程使程序在 python 中运行得更快
【发布时间】:2022-06-12 08:33:53
【问题描述】:

我目前正在开发一个使用两个摄像头的计算机视觉项目,我想通过使用多个线程、进程或 asyncio 来提高程序的速度,但我的经验有限,我不知道如何重写程序的架构,也许你可以给我一些建议,

程序主要使用tkinter opencv和numpy,从两个摄像头读取数据,然后根据获取的数据计算一个结果

这是最小运行示例:

class gui():
    def __init__(self,args):
        some_layout...
        self.root = tk.Tk()
        self.get_data_from_Cam1()
        self.root.mainloop()


    def get_data_from_Cam1(self):
        ..read frame from cam 1..
        self.job = self.root.after(1, self.process_Cam1ata())

     def process_Cam1ata(self):
        ..process_Cam1ata ,You can assume it is an OCR operation..
        self.job = self.root.after(1, self.get_data_from_Cam2())

     def get_data_from_Cam2(self):
        ..read frame from cam 1..
        self.job = self.root.after(1, self.process_Cam2Data())

     def process_Cam2Data(self):
        ..process_Cam2ata.. #High computational capacity 
        self.job = self.root.after(1, self.show_result_on_gui())

     def show_result_on_gui(self):
        ..show result.. 
        self.job = self.root.after(1, self.get_data_from_Cam1())



另外我想问一下tkinter的'after'函数是不是异步操作?

【问题讨论】:

  • “另外我想问一下 tkinter 的 'after' 函数是不是异步操作?” after 只是将要完成的工作放在队列中。这项工作最终与所有其他 GUI 代码在同一个线程中运行。
  • FWIW,您的代码实际上并没有使用 after 来达到任何效果。 after(1, foo()) 将立即运行foo(),然后将结果传递给after
  • 如果您需要做不阻塞 GUI 的工作,那么您需要生成一个线程。线程涉及线程之间的通信。最好用队列来完成。
  • 你真的需要进程——而不是线程! - 每个摄像头一个,一个用于 GUI。进程间通信需要小心。我还没有遇到这个行之有效的队列。套接字真的工作得很好并且高度优化。
  • @jwal 非常感谢你的建议,我试过Sockets,真的很适合我的工作,非常简单优雅的多进程解决方案

标签: python multithreading tkinter python-asyncio


【解决方案1】:

再次感谢@jwal 提出使用套接字的建议。 我重写了我的代码架构,速度确实提高了。

这是最小运行示例:

import socket
import time
from multiprocessing import Process, Queue, Event

class Gui():
  #gui for show frame from client
  def __init__(self,args):
        some_layout...
      self.root = tk.Tk()
      while not self.StopEVENT.is_set():
          self.update_display()
          self.root.update()
          self.root.after(10)
  def update_display(self):
      # try to get frame from two Queues 


def get_data(c, addr, queue_list, StopEVENT):
  #Receive frame from client,will run in subprocess per camera

if __name__ == '__main__':
    StopEVENT = Event()
    s = socket.socket()  
    s.setblocking(False)
    s.bind((host, port))  
    print("Server ON")
    s.listen(5)

    cam1_que = Queue(maxsize=1)
    cam2_que = Queue(maxsize=1)
    queue_list = [cam1_que, cam2_que]
    gui_process = Process(target=Gui, args=(queue_list, StopEVENT))
    gui_process.start()
    process_pool = []
    client_timer = 0
    while True:
        try:
            clientSock, addr = s.accept()
        except BlockingIOError:
            continue
        p = Process(target=get_data, args=(clientSock, addr, queue_list, StopEVENT,))
        process_pool.append(p)
        p.start()
        client_timer += 1
        if client_timer == 2:
            print('All Client connected')
            break
    while not StopEVENT.is_set():
        pass
    s.close()
    gui_process.join()
    gui_process.close()

    for p in process_pool:
        p.kill()
    print('done')

我也试过把所有的Process都换成threading.Thread,也是多线程的版本,还是运行的不错,就是慢了一点。

这是我第一次尝试使用套接字,我很高兴它可以工作,但可能有一些细节可以优化,我会感谢一些改进建议

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2021-05-11
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多