title: Python error with multiprocessing and Tkinter
body: <p>Here is an example of using multiprocessing without Tkinter that works normally. It finds a designated window of another process and tries to set it as the foreground window. I am doing this to allow long-running tasks to run in a separate process from a Tkinter app. The example below is a simplified version of the app that demonstrates the problem.</p>
  
  <p>Worker.py</p>
  
  <pre><code># Worker.py
  import multiprocessing
  
  class Worker:
      def __init__ (self):
          self.work_queue = multiprocessing.Queue()
          self.running = True
          self.process = multiprocessing.Process(target=self.process_commands)
          self.process.start()
      def do_work (self):
          self.work_queue.put('work')
      def do_quit (self):
          self.work_queue.put('quit')
      def process_commands (self):
          while self.running:
              cmd = self.work_queue.get()
              if cmd == 'quit':
                  self.running = False
              elif cmd == 'work':
                  import win32gui
                  hwnd = win32gui.FindWindow(None, 'Untitled - Notepad')
                  win32gui.SetForegroundWindow(hwnd)
  </code></pre>
  
  <p>Main2.py</p>
  
  <pre><code># Main2.py
  import Worker
  
  class App:
      def __init__ (self):
          self.worker = Worker.Worker()
      def do_work (self):
          self.worker.do_work()
      def exit (self):
          self.worker.do_quit()
  
  if __name__ == '__main__':
      app = App()
      app.do_work()
      app.exit()
  </code></pre>
  
  <p>However, when I try to do the same thing from a Tkinter app I get an error.</p>
  
  <p>Main.py</p>
  
  <pre><code># Main.py
  import Tkinter as tk
  import Worker
  
  class App:
      def __init__ (self):
          self.worker = Worker.Worker()
          self.root = tk.Tk()
          self.root.protocol('WM_DELETE_WINDOW', self.exit)
          self.frame = tk.Frame(self.root)
          self.button = tk.Button(self.root, text='Go', command=self.do_work)
          self.button.pack()
          self.statusbar = tk.Label(self.root, text='', bd=1, relief=tk.SUNKEN, anchor=tk.W)
          self.statusbar.pack(side=tk.BOTTOM, fill=tk.X)
          self.update_status('Ready')
          self.frame.pack(fill='both', expand=True)
          self.root.mainloop()
      def do_work (self):
          self.update_status('Doing work...')
          self.worker.do_work()
      def exit (self):
          self.worker.do_quit()
          self.root.quit()
      def update_status (self, status):
          self.statusbar.config(text=status)
          self.statusbar.update_idletasks()
  
  if __name__ == '__main__':
      app = App()
  </code></pre>
  
  <p>Here is the error I get when running the Tkinter app in Main.py:</p>
  
  <pre><code>C:\Scripts\Testing&gt;python Main.py
  Process Process-1:
  Traceback (most recent call last):
    File "C:\Python27\lib\multiprocessing\process.py", line 258, in _bootstrap
      self.run()
    File "C:\Python27\lib\multiprocessing\process.py", line 114, in run
      self._target(*self._args, **self._kwargs)
    File "C:\Scripts\Testing\Worker.py", line 21, in process_commands
      win32gui.SetForegroundWindow(hwnd)
  error: (0, 'SetForegroundWindow', 'No error message is available')
  </code></pre>
  
  <p>One item of note: SetForegroundWindow has a restriction that it must be run from the current foreground window. If you try to call SetForegroundWindow from a background window, it will fail. I thought this might be the problem, but if the process calling SetForegroundWindow was created by the process of the foreground window it will allow it, so I don't think this is the issue. I verified that the worker process is a child process using Process Explorer:</p>
  
  <p><a href="https://i.stack.imgur.com/V8HBk.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/V8HBk.png" alt="Parent and child python.exe processes"></a></p>
  
  <p>I also thought the window handle may be incorrect, but I manually verified the correct window handle is being passed to SetForegroundWindow.</p>
  
  <p><strong>EDIT</strong>: A slightly simpler version, single module and no class, produces the same error:</p>
  
  <p>Main3.py</p>
  
  <pre><code># Main3.py
  import Tkinter as tk
  import multiprocessing
  
  def process_commands (work_queue):
      running = True
      while running:
          cmd = work_queue.get()
          if cmd == 'quit':
              running = False
          elif cmd == 'work':
              import win32gui
              hwnd = win32gui.FindWindow(None, 'Untitled - Notepad')
              print hwnd
              win32gui.SetForegroundWindow(hwnd)
  
  
  class App:
      def __init__ (self):
          self.work_queue = multiprocessing.Queue()
          self.process = multiprocessing.Process(target=process_commands, args=(self.work_queue,))
          self.process.start()
  
          self.root = tk.Tk()
          self.root.protocol('WM_DELETE_WINDOW', self.exit)
          self.frame = tk.Frame(self.root)
          self.button = tk.Button(self.root, text='Go', command=self.do_work)
          self.button.pack()
          self.statusbar = tk.Label(self.root, text='', bd=1, relief=tk.SUNKEN, anchor=tk.W)
          self.statusbar.pack(side=tk.BOTTOM, fill=tk.X)
          self.update_status('Ready')
          self.frame.pack(fill='both', expand=True)
          self.root.mainloop()
      def do_work (self):
          self.update_status('Doing work...')
          self.work_queue.put('work')
      def exit (self):
          self.work_queue.put('quit')
          self.root.quit()
      def update_status (self, status):
          self.statusbar.config(text=status)
          self.statusbar.update_idletasks()
  
  if __name__ == '__main__':
      app = App()
  </code></pre>