Check if current thread is main thread, in Python

This has been answered for Android, Objective C and C++ before, but apparently not for Python. How do I reliably determine whether the current thread is the main thread? I can think of a few approaches, none of which really satisfy me, considering it could be as easy as comparing to threading.MainThread if it existed.

Check the thread name

The main thread is instantiated in threading.py like this:

Thread.__init__(self, name="MainThread")

so one could do

if threading.current_thread().name == 'MainThread'

but is this name fixed? Other codes I have seen checked whether MainThread is contained anywhere in the thread's name.

Store the starting thread

I could store a reference to the starting thread the moment the program starts up, i.e. while there are no other threads yet. This would be absolutely reliable, but way too cumbersome for such a simple query?

Is there a more concise way of doing this?


Solution 1:

The problem with threading.current_thread().name == 'MainThread' is that one can always do:

threading.current_thread().name = 'MyName'
assert threading.current_thread().name == 'MainThread' # will fail

Perhaps the following is more solid:

threading.current_thread().__class__.__name__ == '_MainThread'

Having said that, one may still cunningly do:

threading.current_thread().__class__.__name__ = 'Grrrr'
assert threading.current_thread().__class__.__name__ == '_MainThread' # will fail

But this option still seems better; "after all, we're all consenting adults here."

UPDATE:

Python 3.4 introduced threading.main_thread() which is much better than the above:

assert threading.current_thread() is threading.main_thread()

UPDATE 2:

For Python < 3.4, perhaps the best option is:

isinstance(threading.current_thread(), threading._MainThread)

Solution 2:

The answers here are old and/or bad, so here's a current solution:

if threading.current_thread() is threading.main_thread():
    ...

This method is available since Python 3.4+.

Solution 3:

If, like me, accessing protected attributes gives you the Heebie-jeebies, you may want an alternative for using threading._MainThread, as suggested. In that case, you may exploit the fact that only the Main Thread can handle signals, so the following can do the job:

import signal
def is_main_thread():
    try:
        # Backup the current signal handler
        back_up = signal.signal(signal.SIGINT, signal.SIG_DFL)
    except ValueError:
        # Only Main Thread can handle signals
        return False
    # Restore signal handler
    signal.signal(signal.SIGINT, back_up)
    return True

Updated to address potential issue as pointed out by @user4815162342.