Last active
February 6, 2025 15:42
-
-
Save paulwinex/dc24cfb68faf23363641036663ac1535 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Start process with different options | |
- detached | |
- with new console | |
- with custom envs | |
Example: | |
# python start_process.py --new-console --env PYTHONPATH=/my/path python myscript.py | |
""" | |
import subprocess | |
import os | |
import sys | |
import argparse | |
def start_process( | |
command: list[str] | str, | |
envs: dict = None, | |
detached: bool = False, | |
new_console: bool = False, | |
non_blocking: bool = False, | |
output_file=None | |
): | |
""" | |
Universal function to start a process with different modes. | |
:param command: List of arguments (e.g., ["python", "script.py"]). | |
:param envs: Dictionary of environment variables (e.g., {"PYTHONPATH": "/new/path"}). | |
:param detached: If True, the process will be detached from the parent. | |
:param new_console: If True, the process will start in a new terminal window. | |
:param non_blocking: If True, the process runs as a child but does not block the parent. | |
:param output_file: If provided, redirects the output of a detached process to this file. | |
""" | |
new_env = os.environ.copy() | |
if envs: | |
new_env.update(envs) | |
creationflags = 0 | |
stdin = None | |
start_new_session = False | |
use_shell = False | |
wait_for_process = not detached and not non_blocking # Wait only if not detached or non-blocking | |
stdout = None | |
stderr = None | |
if detached and output_file: | |
stdout = open(output_file, "a") | |
stderr = subprocess.STDOUT | |
elif detached: | |
stdout = open(os.devnull, "w") | |
stderr = subprocess.STDOUT | |
if sys.platform == "win32": | |
if detached: | |
creationflags |= subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS | |
if new_console: | |
creationflags |= subprocess.CREATE_NEW_CONSOLE | |
stdin = subprocess.DEVNULL if detached else None | |
else: | |
if detached: | |
start_new_session = True | |
stdin = open(os.devnull, "r") | |
if new_console: | |
terminal = os.environ.get("TERMINAL", "x-terminal-emulator") | |
if terminal in ["gnome-terminal", "konsole", "xfce4-terminal"]: | |
command = [terminal, "--", *command] | |
else: | |
command = f'{terminal} -e "{subprocess.list2cmdline(command)}"' | |
use_shell = True | |
process = subprocess.Popen( | |
command, | |
env=new_env, | |
stdout=stdout, | |
stderr=stderr, | |
stdin=stdin, | |
close_fds=True if sys.platform != "win32" else False, | |
start_new_session=start_new_session, | |
creationflags=creationflags, | |
shell=use_shell | |
) | |
if detached and output_file: | |
stdout.close() | |
if wait_for_process: | |
process.wait() | |
if __name__ == "__main__": | |
import argparse | |
parser = argparse.ArgumentParser(description="Start a process with different execution modes") | |
parser.add_argument("--detached", action="store_true", help="Run the process in the background") | |
parser.add_argument("--new-console", action="store_true", help="Run the process in a new terminal window") | |
parser.add_argument("--non-blocking", action="store_true", help="Run the process as a child without blocking the parent") | |
parser.add_argument("--env", action="append", help="Environment variables in the format KEY=VALUE", default=[]) | |
parser.add_argument("--output-file", help="File to redirect output of a detached process") | |
parser.add_argument("command", nargs=argparse.REMAINDER, help="Command to execute") | |
args = parser.parse_args() | |
if not args.command: | |
parser.error("No command provided for execution") | |
env_vars = {key: value for key, value in (env.split("=", 1) for env in args.env)} if args.env else None | |
start_process( | |
args.command, | |
envs=env_vars, | |
detached=args.detached, | |
new_console=args.new_console, | |
non_blocking=args.non_blocking, | |
output_file=args.output_file | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment