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

Python, show output of multiple processes in different parts of the terminal

我是运行一个在Python的多处理系统,我打算把终端window分成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 模块来实现这种可视化。
基本上在每个过程中我都创建了一个不同的 window。两者具有相同的 height/width(rows_mid、cols_mid),但想法是进程 01 的 window 应该起源于 (0,0),而进程 01 的 window 应该起源于坐标(0,cols_mid)处的process02,像这样:

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, 0)
    self.win.addstr(0, 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, 0, x_mid)
    self.win.addstr(0, 0, "*** PROCESS 02 ***")
    self.win. addstr(whatever)

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

我能以某种方式修复它吗?是否有 better/easier 替代使用 curses 的方法?

如评论中所述:

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

  2. 万一有人想坚持'manual'方法,问题似乎是各种进程相互干扰,所以屏幕被它们中的每一个覆盖。

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

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, 0)
    win12 = curses.newwin(rows_mid, cols_mid, 0, cols_mid)
    win21 = curses.newwin(rows_mid, cols_mid, rows_mid, 0)
    win22 = curses.newwin(rows_mid, cols_mid, rows_mid, cols_mid)
    win11.addstr(0, 0, "*** PROCESS 01 ***", curses.A_BOLD)
    win12.addstr(0, 0, "*** PROCESS 02 ***", curses.A_BOLD)
    win21.addstr(0, 0, "*** PROCESS 03 ***", curses.A_BOLD)
    win22.addstr(0, 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, 0, 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, 0, message)
        win12.clrtoeol()

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

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

    

其他进程也类似