stdcerr
stdcerr

Reputation: 15598

Python script doesn't restart itself properly

I have a Python script and I want to have it restart itself. I found the following lines Googling around:

def restart_program():
    """Restarts the current program.
    Note: this function does not return. Any cleanup action (like
    saving data) must be done before calling this function."""
    python = sys.executable
    os.execl(python, python, * sys.argv)

but problems became apparent right after trying this out. I'm running on a really small embedded system and I ran out of memory really quick (after 2 or three iterations of this function). Checking the process list, I can see a whole bunch of python processes. Now, I realize, I could check the process list and kill all processes that have another PID than myself - is this what I have to do or is there a better Python solution?

Upvotes: 2

Views: 880

Answers (2)

stdcerr
stdcerr

Reputation: 15598

I rewrote my restart function as follows, it will kill every python process other than itself before launching the new sub process:

def restart_program():
    """Restarts the current program.
    Note: this function does not return. Any cleanup action (like
    saving data) must be done before calling this function."""
    logger.info("RESTARTING SCRIPT")
    # command to extract the PID from all the python processes
    # in the process list
    CMD="/bin/ps ax | grep python | grep -v grep | awk '{ print $1 }'"
    #executing above command and redirecting the stdout int subprocess instance
    p = subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE)
    #reading output into a string
    pidstr = p.communicate()[0]
    #load pidstring into list by breaking at \n
    pidlist = pidstr.split("\n")
    #get pid of this current process
    mypid = str(os.getpid())
    #iterate through list killing all left over python processes other than this one
    for pid in pidlist:
        #find mypid
        if mypid in pid:
            logger.debug("THIS PID "+pid)
        else:
            #kill all others
            logger.debug("KILL "+pid)
            try:
                pidint = int(pid)
                os.kill(pidint, signal.SIGTERM)
            except:
                logger.error("CAN NOT KILL PID: "+pid)


    python = sys.executable
    os.execl(python, python, * sys.argv)

Not exactly sure if this is the best solution but it works for the interim anyways...

Upvotes: 1

Thomas Orozco
Thomas Orozco

Reputation: 55207

This spawns a new child process using the same invocation that was used to spawn the first process, but it does not stop the existing process (more precisely: the existing process waits for the child to exit).

The easier way would be to refactor your program so you don't have to restart it. Why do you need to do this?

Upvotes: 2

Related Questions