Search code examples
pythonpython-3.xsubprocessfreezepsutil

How can I avoid Python hanging on subprocess.run()


I am creating a small automation script to interact with a game. The game is very vulnerable to crashing, but in an unpredictable way (after 30 minutes to 3 hours, depending on what happens in game). Because of this, I wrote a small script below that was IDEALLY going to kill the program, kill the crash monitoring client that checks for crashes and offers to restart, and then relaunch the game and resume. The issue is that I never reach past subprocess.run()

it launches the game again, but it does not allow for any code after that to run.

import psutil
import time
import subprocess

def main():
    '''Process kill function'''    
    for proc in psutil.process_iter():
        # check whether the process name matches
        # print(proc.name())
        if any(procstr in proc.name() for procstr in\
            ['GameName.exe']):
            print(f'Killing {proc.name()}')
            proc.kill()
            time.sleep(5)
    for proc in psutil.process_iter():
        # check whether the process name matches
        # print(proc.name())
        if any(procstr in proc.name() for procstr in\
            ['GameCrashMonitor.exe']):
            print(f'Killing {proc.name()}')
            proc.kill()
    time.sleep(10)
    subprocess.run(r'PathToGame.exe')
    print(time.time())

if __name__ == "__main__":
    main()

This program successfully gets to subprocess.call, launches the game again, and then python hangs. I cant control c on ipython to stop it. I use Spyder and it even makes the icon for spyder on my task bar error and disappear.


Solution

  • Try replacing subprocess.run() with variable = subprocess.Popen([r'PathToGame.exe']) https://docs.python.org/3/library/subprocess.html says that subprocess.run() waits for the command to complete, then returns a CompletedProcess instance. Your command isnt completing. Furthermore, there is a timeout argument you could pass into run() but by default, it is None, and does not time out, if you wanted to still use .run()