thread fails to start if wx.app.mainloop isn't called from the main module
Question: I'm hoping someone can explain this behavior to me. If I import a module that
starts a wxpython interface, threads are unable to start until after the
app.MainLoop() ends. Simplest example:

simple_app.py

    
    
    import wx
    from threading import Thread
    
    def test():
        from time import sleep
        while 1:
            print("thread still running")
            sleep(2)
    
    app = wx.App() 
    frame = wx.Frame(None, -1, 'simple.py')
    frame.Show()
    thread = Thread(target=test)
    thread.setDaemon(True)
    thread.start()
    app.MainLoop()
    

main.py

    
    
    import simple_app
    

If you run simple_app.py by itself it works fine, if you run main.py the
thread never starts... Why? I have a feeling it has to do with the thread
being unable to secure a lock.


Answer: The second thread in `simple_app.py` is trying to import the `time` module
while an import is already running, which leads to deadlock when `simple_app`
is being imported from the main module. Because imports acquire interpreter's
import lock for the current thread while importing a module. It has been
[documented](https://docs.python.org/2/library/threading.html#importing-in-
threaded-code).

Threads in the main module can import other modules that's why running
`simple_app.py` as main module works. Moving `from time import sleep` to
module level in `simple_app.py` solves the problem.

Running the following code helps better understand the problem;

my_time.py  
`from time import sleep`

simple_app.py

    
    
    import imp
    import sys
    from threading import Thread
    from time import sleep
    
    import wx
    
    class MyFinder(object):
        def __init__(self):
            print('MyFinder initializing')
            if imp.lock_held():
                while imp.lock_held():
                    print('import lock held')
                    sleep(2)
                print('import lock released')
            else:
                print('import lock is not held')
    
        def find_module(self, module, package=None):
            print('MyFinder.find_module called with module name "{}", pakcage name "{}"'.format(module, package))
            return None
    
    
    def test():
        sys.meta_path.append(MyFinder())
        from my_time import sleep
        count = 0
        while True:
            print("{} thread still running".format(count))
            count += 1
            sleep(2)
    
    
    app = wx.App()
    frame = wx.Frame(None, -1, 'simple.py')
    frame.Show()
    thread = Thread(target=test)
    thread.setDaemon(True)
    thread.start()
    app.MainLoop()
    

