title: Python curses string input while continuously updating a separate window?
body: <p>How can I simultaneously read a string as input in one window while updating another window? This is for using curses in Python.</p>
  
  <p>This would be useful e.g. for having a program that displays some output which can happen at any time, even when the user is typing. The idea being that the user can continue to type without having the currently entered, semi-complete string get truncated or cut in the middle due to sudden output from the program.</p>
  
  <p>I've tried to use and modify the code from this question: <a href="https://stackoverflow.com/questions/26152942/python-curses-user-input-while-updating-screen">Python/curses user input while updating screen</a></p>
  
  <p>Since the code already exists in the other question I'm not posting it again here.</p>
  
  <p>However, this code only reads a single character.</p>
  
  <p>I can't just call getstr, as this will block and stop updating the other window until the user has entered a full string.</p>
  
  <p>It might seem obvious how to solve it: Use threads. However, this is already warned against in the aforementioned question---curses doesn't play well with threads in Python, it seems.</p>
  
  <p>Another "obvious" way to solve it would be to implement your own buffer, read one character at a time, implement basic editing, and keep using select to this in a non-blocking manner.</p>
  
  <p>I am hoping that there is some way to read a string in a non-blocking manner while providing basic line editing (so I don't need to implement it myself!) using curses, as I can imagine this is a rather typical use case.</p>
  
  <p>Here is an attempt using threading, modified from the aforementioned example code. The problem with this code is that it garbles the display. The display remains garbled until the window is resized, then it appears fine.</p>
  
  <p>The code reads user input in one window (one thread), grabs a mutex, gives the string to some shared string, the other thread grabs the mutex, and displays it.</p>
  
  <p>What is wrong with this code? What causes the garbled output? As soon as I remove the other thread manipulating curses (removing the getstr call), it stops being garbled.</p>
  
  <pre><code>#!/usr/bin/python
  # -*- coding: iso-8859-1 -*-
  
  import curses, curses.panel
  import random
  import time
  import sys
  import select
  import threading
  
  gui = None
  
  class ui:
      def __init__(self):
          self.output_mutex = threading.Lock()
          self.output_str = ""
  
          self.stdscr = curses.initscr()
  #        curses.noecho()
          curses.echo()
          curses.cbreak()
          curses.curs_set(0)
          self.stdscr.keypad(1)
  
          self.win1 = curses.newwin(10, 50, 0, 0)    
          self.win1.border(0)
          self.pan1 = curses.panel.new_panel(self.win1)
          self.win2 = curses.newwin(10, 50, 0, 0)    
          self.win2.border(0)
          self.pan2 = curses.panel.new_panel(self.win2)
          self.win3 = curses.newwin(10, 50, 12, 0)
          self.win3.border(0)
          self.pan3 = curses.panel.new_panel(self.win3)
  
          self.win1.addstr(1, 1, "Window 1")
          self.win2.addstr(1, 1, "Window 2")
  
  #        self.win3.addstr(1, 1, "Input: ")
  #   user_input = self.win3.getstr(8, 1, 20)
  #        self.win3.addstr(2, 1, "Output: %s" % user_input)
  
  #        self.pan1.hide()
  
      def refresh(self):
          curses.panel.update_panels()
          self.win3.refresh()
          self.win2.refresh()
          self.win1.refresh()
  
      def quit_ui(self):
          curses.nocbreak()
          self.stdscr.keypad(0)
          curses.curs_set(1)
          curses.echo()
          curses.endwin()
          print "UI quitted"
          exit(0)
  
  
  def worker_output(ui):
      count = 0
      running = 1
  
      while True:
          ui.win2.addstr(3, 1, str(count)+": "+str(int(round(random.random()*999))))
          ui.win2.addstr(4, 1, str(running))
  
          ui.output_mutex.acquire()
  
          ui.win2.addstr(5, 1, ui.output_str)
  
          ui.output_mutex.release()
  
          ui.refresh()
          time.sleep(0.1)
  
  
  class feeder:
      # Fake U.I feeder
      def __init__(self):
          self.running = False
          self.ui = ui()
          self.count = 0
  
      def stop(self):
          self.running = False
  
      def run(self):
          self.running = True
          self.feed()
  
      def feed(self):
          threads = []
          t = threading.Thread(target=worker_output, args=(self.ui,))
          threads.append(t)
          t.start()
  
          user_input = ""
  
          while True:
              self.ui.win3.addstr(1, 1, "Input: ")
              user_input = self.ui.win3.getstr(1, 8, 20)
              self.ui.win3.addstr(2, 1, "Output: %s" % user_input)
  #            self.ui.refresh()
  #            self.ui.win3.clear()
  
              self.ui.output_mutex.acquire()
  
              self.ui.output_str = user_input
  
              self.ui.output_mutex.release()
  
              time.sleep(.2)
  
  
  if __name__ == "__main__":
      f = feeder()
      f.run()
  </code></pre>