Restarting a Python script from within itself can be useful for various reasons: recovering from unrecoverable errors, reloading configuration, or implementing a simple update mechanism.
This guide explains different methods to restart a Python script, emphasizing the recommended approach (os.execv()) and outlining the pros and cons of alternatives.
Restarting with os.execv() (Recommended)
The os.execv() function is the best and safest way to restart a Python script. It replaces the current process with a new one, running the same script. This is much cleaner than launching a new, separate process.
import os
import sys
import time # Import the time module
def restart():
print('Restarting script in 3 seconds...') # Clearer output.
time.sleep(3) # Added delay
os.execv(sys.executable, [sys.executable] + sys.argv)
restart()
print("This line will NOT be reached in the original process.") # Clarified commentsys.executable: This variable holds the absolute path to the Python interpreter (e.g.,/usr/bin/python3orC:\Python39\python.exe).sys.argv: This is a list of the command-line arguments passed to the script.sys.argv[0]is the script name itself. We include this so that any arguments your script uses are passed to the restarted version.os.execv(executable, args): This is the core of the restart.executable: The path to the new program to execute (our Python interpreter).args: A list of strings representing the arguments to the new program. We're essentially building the commandpython your_script.py [any original arguments].time.sleep(3): This adds a 3-second delay before restarting. This is often useful to prevent rapid restart loops in case of errors.
You might need to adjust the Python executable name for different systems:
os.execv(sys.executable, ['python3'] + sys.argv)
os.execv(sys.executable, ['py'] + sys.argv)Restarting with os.system() (Not Recommended)
os.system() executes a command in a new subshell. While you can use it to start a new instance of your script, it's strongly discouraged for restarting.
import os
import time
print('Restarting using os.system()...')
time.sleep(3)
os.system('python main.py') # Starts a NEW process.
print("This WILL print, but in the *original* process.") # added a warningRestarting a Script Indefinitely
To restart a script continuously, combine os.execv() with a while True loop:
import os
import sys
import time
while True:
print('Running script...')
time.sleep(3) # Simulate work being done
print('Restarting...')
os.execv(sys.executable, [sys.executable] + sys.argv)Restarting with psutil (Advanced)
The psutil library provides more control over processes. It's useful for gracefully restarting a script, ensuring file handles and connections are closed. This is a more advanced technique.
import sys
import os
import psutil
import time
def restart_script():
try:
p = psutil.Process(os.getpid())
for handler in p.open_files() + p.connections():
try: # Add a try/except to close each handle.
os.close(handler.fd)
except Exception as e:
print(f"Error closing handle: {e}")
except Exception as e:
print(e)
python = sys.executable
print("Restarting in 3 seconds...")
time.sleep(3)
os.execl(python, python, *sys.argv)
print('Running...')
restart_script()
print("This will NEVER be reached.")- The code attempts to close all file descriptors and network connections before calling
os.execl. The newtry/exceptblock is very important to prevent the program from crashing if a file descriptor can not be closed.
Restarting with a Bash Script (Platform-Specific)
For Unix-like systems (Linux, macOS), you can use a bash script to kill any running instances of your script and then start a new one:
pkill -f main.py # Kill any existing processes running main.py. CAREFUL!
python main.py & # Run in the backgroundimport os
import subprocess
subprocess.run(['chmod', '+x', 'restart-script.sh'], check=False) # Use check=False because chmod won't work on windows
print('Running main.py...')
os.execl('./restart-script.sh', '&') # Execute the script
print("This line will NEVER be reached.")