Search code examples
pythonuser-interfacetkinterpsutil

How to ensure only one instance of a Tkinter executable Python script is running?


I'm developing a Tkinter-based GUI application in Python, and after converting it to an executable using tools like PyInstaller or pytoexe, I encountered an issue where launching the executable multiple times opens multiple windows instead of focusing the existing one.

I want to restrict my application to a single instance, so if the user attempts to open the executable again, it either displays a messagebox indicating that the application is already running, or it brings the existing window to the front and focuses on it.

I've tried using psutil to check for existing processes or making the root window a static variable, but these approaches didn't work as expected.

Could someone please suggest a reliable method or code snippet to achieve this behavior in a cross-platform manner, particularly on Windows and Linux?


Solution

  • Here is a stand alone program that will run if another copy of itself is not running. The example "program" at the bottom simply waits 10 seconds and terminates. If you run a second copy during that time it will just report an message and terminate immediately. You can pull the boolean function "i_am_the_only_one" into your code for usage.

    #!/usr/bin/env python3
    
    import os
    import tempfile
    import time
    
    
    def is_process_running(pid):
        try:
            os.kill(pid, 0)
        except OSError:
            return False
        else:
            return True
    
    def i_am_the_only_one():
        current_pid = os.getpid()
        temp_file_path = os.path.join(tempfile.gettempdir(), 'process_id.tmp')
        if os.path.exists(temp_file_path):
            with open(temp_file_path, 'r') as temp_file:
                content = temp_file.read().strip()
                if content:
                    try:
                        existing_pid = int(content)
                        if is_process_running(existing_pid):
                            return False
                    except ValueError:
                        print("Temp file contains invalid PID.")
        with open(temp_file_path, 'w') as temp_file:
            temp_file.write(str(current_pid))
        return True
    
    # Example usage
    if __name__ == "__main__":
        if i_am_the_only_one():
            print("run program here")
            time.sleep(10)
        else:
            print("Another instance is already running.")