admin管理员组文章数量:1429954
I want to run a python script B
in the background every 8 hours on a Windows machine that usually runs 24/7. Also, I have another script A
that is manually executed and uses data that is provided by the background script (which queries a large database and extracts relevant data so that it is avl. for the main script w/o long waiting times).
The question is: How can I assure that B
is running when A
is started?
My idea is when starting A
to somehow check whether B
already exists, and if not launch it via multiprocessing.Process
. But how can I identify this process?
Only thing I came up with would be saving the process id somewhere in a file to disk and then check every time whether a process with this id exists - but afaik this id must not necessarily refer to my process in case that one crashed and Windows gave the same id to another process in the meantime.
I want to run a python script B
in the background every 8 hours on a Windows machine that usually runs 24/7. Also, I have another script A
that is manually executed and uses data that is provided by the background script (which queries a large database and extracts relevant data so that it is avl. for the main script w/o long waiting times).
The question is: How can I assure that B
is running when A
is started?
My idea is when starting A
to somehow check whether B
already exists, and if not launch it via multiprocessing.Process
. But how can I identify this process?
Only thing I came up with would be saving the process id somewhere in a file to disk and then check every time whether a process with this id exists - but afaik this id must not necessarily refer to my process in case that one crashed and Windows gave the same id to another process in the meantime.
Share Improve this question asked Nov 19, 2024 at 14:16 ascripterascripter 6,26512 gold badges54 silver badges72 bronze badges2 Answers
Reset to default 0Use a File-Based Lock**. It's simple, robust, and doesn't require external tools.
Script B (Background Script):
import os
import time
LOCK_FILE = 'script_b.lock'
def is_running():
"""Check if the lock file exists."""
return os.path.exists(LOCK_FILE)
def create_lock_file():
"""Create the lock file and write the current process ID."""
with open(LOCK_FILE, 'w') as f:
f.write(str(os.getpid()))
def remove_lock_file():
"""Remove the lock file."""
if os.path.exists(LOCK_FILE):
os.remove(LOCK_FILE)
try:
if is_running():
print("Script B is already running.")
exit(0) # Exit if already running
create_lock_file()
print("Script B is running in the background...")
# Simulate continuous work (replace this with your actual logic)
while True:
time.sleep(1)
finally:
remove_lock_file()
Script A (Main Script):
import os
import psutil
import subprocess
LOCK_FILE = 'script_b.lock'
def get_running_pid():
"""Get the PID from the lock file if it exists."""
if os.path.exists(LOCK_FILE):
with open(LOCK_FILE, 'r') as f:
return int(f.read().strip())
return None
def is_process_running(pid):
"""Check if a process with the given PID is still running."""
try:
p = psutil.Process(pid)
return p.is_running()
except (psutil.NoSuchProcess, ValueError):
return False
def start_script_b():
"""Start Script B as a detached process."""
print("Starting Script B...")
subprocess.Popen(['python', 'script_b.py'], creationflags=subprocess.DETACHED_PROCESS)
pid = get_running_pid()
if pid and is_process_running(pid):
print(f"Script B is running with PID {pid}.")
else:
print("Script B is not running. Starting it now.")
start_script_b()
How It Works:
- Script B creates a lock file (
script_b.lock
) with its process ID when it starts. If the lock file exists, it assumes it's already running. - Script A checks the lock file for a PID and verifies if the process is active using the
psutil
library. - If Script B is not running, Script A launches it using
subprocess.Popen
.
Dependencies:
- The
psutil
library for process checks (pip install psutil
). - Ensure both scripts are in the same directory or adjust file paths accordingly.
This solution keeps things lightweight, Python-only, and easy to manage!
I would create the following module that will start an arbitrary Python script as a detached process if and only if the script is not already running (this requires the psutil
and FileLock
modules from the PyPi repository). The code recognizes that the required script is running by searching all the currently executing processes looking for the (hopefully) unique script name.
start_script.py
from subprocess import Popen, DETACHED_PROCESS
import sys
from filelock import FileLock
import psutil
def start_script(script_name: str, needs_console=True) -> None:
"""Start script if it is not already running as a new, detached process.
If needs_console is True (the default), then the Windows start command
is used to provide a new console.
"""
lock_file = script_name + '.lock'
with FileLock(lock_file):
for process in psutil.process_iter(['cmdline']):
cmdline = process.info['cmdline']
if cmdline and len(cmdline) > 1 and cmdline[1] == script_name:
return # Already running
# Here if the script is not already running
if needs_console:
# Use Windows start command
Popen(['start', sys.executable, script_name], creationflags=DETACHED_PROCESS, shell=True)
else:
Popen([sys.executable, script_name], creationflags=DETACHED_PROCESS)
Then instead of ever executing Script B directly with python scriptB.py
, create a new script that will ensure that only a single instance of sciptB.py is ever running:
:
start_scriptB
from start_script import start_script
SCRIPT_B_PATH = r'\some-directory-path\scriptB.py'
def startB():
start_script(SCRIPT_B_PATH)
if __name__ == '__main__:
startB()
Your scheduler will now periodically run the above script instead.
Finally, Script A would contain:
from start_scriptB import startB
...
startB() # Start Script B if it is not already running
NB: Testing whether a script is running and then starting the script if it is not constitutes a critical section, i.e. these two operations must appear to be atomic to ensure that you cannot have two instances of the script executing concurrently. That is why both operations are performed under the control of an acquired FileLock
instance.
本文标签:
版权声明:本文标题:multiprocessing - How to identify and manage a background daemon process beyond parent process runtime in python - Stack Overflo 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745555628a2663169.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论