title: Capture python stdout in real time
body: <p>I have a GUI program <code>guy.py</code> (that uses tkinter) and a command line script <code>script.py</code>. I want to launch the script from the program and write its output to a textbox in the GUI. Because the script takes quite some time to run (up to 15 minutes), and I want to monitor it, I want the script to write the output in real time inside the textbox, while it's being written, not just when it has finished executing.</p>
  <p>I've found some <a href="https://stackoverflow.com/a/3333386">other questions</a> dealing with this problem. Here is the code of <code>gui.py</code> I've developed until now (the real code is too big to post here, but here's the most important part)</p>
  <pre class="lang-py prettyprint-override"><code>import tkinter as tk
  
  # redirector class
  class StdoutRedirector:
      def __init__(self, textbox):
          self.textbox = textbox
  
      def write(self, str):
          self.textbox.insert(tk.END, str)
  
  # gui application
  class GuiApp:
      def __init__():
          self._out = StdoutRedirector(self.builder.get_object('textbox1')) # this just takes a reference to the tkinter text
  
      def button_callback(self):
          sys.stdout = self._out
          print(&quot;test&quot;) # this will print to the textbox
          subprocess.Popen(['python3', 'script.py']) # this will not print to the textbox
  </code></pre>
  <p>This will print the output to the &quot;normal&quot; output, so I've tried telling subprocess what to use as stdout, by changing the last line to</p>
  <pre class="lang-py prettyprint-override"><code>subprocess.Popen(['python3', 'script.py'], stdout=self._out)
  </code></pre>
  <p>This results in an exception, because (differently from <code>print()</code>), <code>Popen()</code> needs a file descriptor. Of course giving a <code>fileno</code> of 1 will just print to stdout, giving any other number will throw an error</p>
  <pre><code>  File &quot;/usr/lib/python3.8/tkinter/__init__.py&quot;, line 1892, in __call__
      return self.func(*args)
    File &quot;./guy.py&quot;, line 64, in convert_sdatb
      subprocess.Popen(['python3', 'test_subprocess.py'], stdout=self._out)
    File &quot;/usr/lib/python3.8/subprocess.py&quot;, line 808, in __init__
      errread, errwrite) = self._get_handles(stdin, stdout, stderr)
    File &quot;/usr/lib/python3.8/subprocess.py&quot;, line 1489, in _get_handles
      c2pwrite = stdout.fileno()
  AttributeError: 'StdoutRedirector' object has no attribute 'fileno'
  </code></pre>
  <p>How can I make that the output of my script is redirected in real time (as it's written) directly in my class?</p>