title: Screen-like split screen for output of multiprocess python
body: <p>I'm often in the situation that I have to run some time-intensive code on a larg number of inputs, and want to speed it up running multiple instances of the code in parallel (on different CPU-cores or Cuda-devices).</p>
  
  <p>So far I done it by hand:</p>
  
  <ul>
  <li>Open screen/tmux</li>
  <li>create split-planes</li>
  <li>run the code with only a fraction of the inputs in each pane</li>
  </ul>
  
  <p>This is however cumbersome, error-prone and doesn't work in cases where the are non-parallel parts of code. I therefore sometimes used multiprocessing.Pool to run the code in parallel but this does not work if I want/need to be able to read the output of the different parts and will get a mess if the (third-party) code that runs in parallel contains things like tqdm.</p>
  
  <p>I would like create a split screen and write the stdout/stderr of each of the different processes to one of the split panes. I however haven't found any package/trick to do this properly.
  I played with urwind, ncurses &amp; prompt_toolkit but they are not meant to serve stdout/stderr.</p>
  
  <p>My current best – hacky – solution is using libtmux:</p>
  
  <pre><code>import os
  import sys
  import tempfile
  import time
  from multiprocessing import Pool, current_process
  
  import libtmux
  from tqdm import tqdm
  
  tmpdir = tempfile.mkdtemp()
  fifo1_name = os.path.join(tmpdir, "fifo1")
  fifo2_name = os.path.join(tmpdir, "fifo2")
  os.mkfifo(fifo1_name)
  os.mkfifo(fifo2_name)
  session_name = "session_name"
  
  
  def setup(para):
      """Change stdout/stderr to point to the fifo connected to the right tmux plane"""
      pid = int(current_process().name.split("-")[-1])
      if pid % 2 == 0:
          fifo_write = open(fifo1_name, "w", 1)
      else:
          fifo_write = open(fifo2_name, "w", 1)
      sys.stdout = fifo_write
      sys.stderr = fifo_write
      run(para, pid)
  
  
  def run(para, pid):
      """Dummy function"""
      print("start run nr.", para, "on", pid)
      for _ in tqdm(range(10), desc=str(para)):
          time.sleep(1)
      print("finished run nr.", para)
  
  
  parameter_space = [1, 2, 3, 4, 5, 6]
  
  # Set up tmux
  server = libtmux.Server()
  session = server.find_where({"session_name": session_name})
  if session is None:
      session = server.new_session(
          session_name=session_name, window_command="cat " + fifo1_name
      )
      window = session.windows[0]
      window.panes[0]
      window.split_window(shell="cat " + fifo2_name)
  # session.attach_session() Does not work for unknown reasons the planes stay empty
  
  # Run always 2 runs in parallel
  with Pool(2) as p:
      p.map(setup, parameter_space)
  
  if session:
      session.kill_session()
  </code></pre>
  
  <p>This still has the problem, that I must manually attach to the session, since <code>attach_session()</code> leads to empty panes. Also it feels like a hacky and ugly workaround.</p>
  
  <p>Is there a better/nicer way?</p>