Python,在终端的不同部分显示多个进程的输出

问题描述

我在 Python 中运行一个多处理系统,我计划将终端窗口划分为 4 个象限,并在其中一个象限中显示每个进程的输出

所以,最终的输出应该是这样的:

----------------------------------
|                |                |
|   PROCESS_01   |   PROCESS_02   |
|                |                |
----------------------------------
|                |                |
|   PROCESS_03   |   PROCESS_04   |
|                |                |
----------------------------------

我有一个文件,从那里开始单个进程:

if __name__ == "__main__":
    set_start_method("spawn")

    p01 = mp.Process(target=p01_Initializer,args=(...))
    p01.daemon = True
    p01.start()

    p02 = mp.Process(target=p02_Initializer,args=(...))
    p02.daemon = True
    p02.start()

    p03 = mp.Process(target=p03_Initializer,args=(...))
    p03.daemon = True
    p03.start()

    p04 = mp.Process(target=p04_Initializer,args=(...))
    p04.daemon = True
    p04.start()


我打算使用curses模块来实现这种可视化。
基本上在每个过程中我都创建了一个不同的窗口。两者具有相同的高度/宽度(rows_mid,cols_mid),但其想法是进程 01 的窗口应起源于 (0,0),而进程 02 的窗口应起源于坐标 (0,cols_mid),如下所示:>

PROCESS_01


    curses.initscr()
    cols_tot = curses.COLS
    rows_tot = curses.LInes
    x_mid = int(0.5*cols_tot)
    y_mid = int(0.5*rows_tot)
    self.win = curses.newwin(y_mid,x_mid,0)
    self.win.addstr(0,"*** PROCESS 01 ***")
    self.win. addstr(whatever)

PROCESS_02


    curses.initscr()
    cols_tot = curses.COLS
    rows_tot = curses.LInes
    x_mid = int(0.5*cols_tot)
    y_mid = int(0.5*rows_tot)
    self.win = curses.newwin(y_mid,x_mid)
    self.win.addstr(0,"*** PROCESS 02 ***")
    self.win. addstr(whatever)

但它并没有真正起作用。一开始,只有 PROCESS_02 的输出被可视化,在正确的位置。 然后,只有 PROCESS_01 出现,但一些东西在 PROCESS_02 的输出应该是的空间中可视化,就像这样

Initial behavior

Fianl output

我能以某种方式修复它吗?有没有比使用诅咒更好/更简单的替代方法

解决方法

如评论中所述:

  1. 我可以通过将输出写入日志文件并使用 tmux 以更简单的方式获得相同的结果;

  2. 如果您想坚持使用“手动”方法,问题似乎是各个进程相互干扰,因此屏幕会被每个进程覆盖。

我通过将每个进程的所有输出收集在一个数组中来解决它,然后通过队列将其发送回主进程并在那里打印。

PROCESS_01


    output_messages_01 = []
    output_messages_01.append('first output of P01')
    output_messages_01.append('second output of P01')
    ....

    ## limiting overall number of messages in the array (if too many,it gets out of the window row limit when printing them in terminal)
    if len(output_messages_01)>15:
                output_messages_01 = output_messages_01[-15:]
    output_queue_p01.put((output_messages_01))

PROCESS_02


    output_messages_02 = []
    output_messages_02.append('first output of P02')
    output_messages_02.append('second output of P02')
    ....
    if len(output_messages_02)>15:
                output_messages_02 = output_messages_02[-15:]
    output_queue_p02.put((output_messages_02))

并且,在主要过程中,我收集并打印所有内容

主要流程

    ## creating panels
    win11 = curses.newwin(rows_mid,cols_mid,0)
    win12 = curses.newwin(rows_mid,cols_mid)
    win21 = curses.newwin(rows_mid,rows_mid,0)
    win22 = curses.newwin(rows_mid,cols_mid)
    win11.addstr(0,"*** PROCESS 01 ***",curses.A_BOLD)
    win12.addstr(0,"*** PROCESS 02 ***",curses.A_BOLD)
    win21.addstr(0,"*** PROCESS 03 ***",curses.A_BOLD)
    win22.addstr(0,"*** PROCESS 04 ***",curses.A_BOLD)

    ## getting array with output message from process01
    p01_messages = output_queue_p01.get()
    for row,message in enumerate(p01_messages):
        win11.addstr(row,message)
        win11.clrtoeol()
    
    ## getting array with output message from process02
    p02_messages = output_queue_p02.get()
    for row,message in enumerate(p02_messages):
        win12.addstr(row,message)
        win12.clrtoeol()

   ## same thing for processes 03 and 04 ...

    win11.refresh()
    win12.refresh()
    win21.refresh()
    win22.refresh()

    

其他进程类似