98 lines
2.7 KiB
Python
98 lines
2.7 KiB
Python
import subprocess
|
|
import sys
|
|
import os
|
|
import platform
|
|
import shutil
|
|
from typing import List, Optional
|
|
from .paths import ROOT_DIR # centralized project paths
|
|
|
|
|
|
def _find_terminal_emulator() -> Optional[str]:
|
|
"""
|
|
Try to find an available terminal emulator on Linux.
|
|
Returns the command name if found, otherwise None.
|
|
"""
|
|
candidates = [
|
|
"x-terminal-emulator",
|
|
"gnome-terminal",
|
|
"konsole",
|
|
"xfce4-terminal",
|
|
"lxterminal",
|
|
"mate-terminal",
|
|
"tilix",
|
|
"terminator",
|
|
"xterm"
|
|
]
|
|
for term in candidates:
|
|
if shutil.which(term):
|
|
return term
|
|
return None
|
|
|
|
|
|
def new_python_process(
|
|
script_path: str,
|
|
python_exec: str = sys.executable,
|
|
args: Optional[List[str]] = None,
|
|
cwd: str = str(ROOT_DIR),
|
|
wait: bool = False,
|
|
new_console: bool = False
|
|
) -> int:
|
|
"""
|
|
Start a new Python process running the given script.
|
|
|
|
Args:
|
|
script_path (str): Path to the Python script to execute.
|
|
python_exec (str): Path to the Python executable.
|
|
args (List[str], optional): Arguments to pass to the script. Defaults to [].
|
|
cwd (str): Working directory for the process. Defaults to project root.
|
|
wait (bool): If True, waits for process completion. Defaults to False.
|
|
new_console (bool): If True, tries to open process in a new console window.
|
|
|
|
Returns:
|
|
int: PID of the created process.
|
|
"""
|
|
if not os.path.isabs(python_exec):
|
|
python_exec = os.path.normpath(os.path.join(cwd, python_exec))
|
|
|
|
if not os.path.isabs(script_path):
|
|
script_path = os.path.normpath(os.path.join(cwd, script_path))
|
|
|
|
if args is None:
|
|
args = []
|
|
|
|
command = [python_exec, script_path] + args
|
|
|
|
creation_flags = 0
|
|
shell = False
|
|
|
|
system = platform.system().lower()
|
|
|
|
if new_console:
|
|
if system == "windows":
|
|
creation_flags = subprocess.CREATE_NEW_CONSOLE
|
|
elif system == "linux":
|
|
term = _find_terminal_emulator()
|
|
if term:
|
|
command = [term, "-e"] + command
|
|
else:
|
|
# fallback: run in same terminal
|
|
pass
|
|
elif system == "darwin": # MacOS
|
|
osa_cmd = f'tell app "Terminal" to do script "{python_exec} {script_path} {" ".join(args)}"'
|
|
process = subprocess.Popen(["osascript", "-e", osa_cmd], cwd=cwd)
|
|
if wait:
|
|
process.wait()
|
|
return process.pid
|
|
|
|
process = subprocess.Popen(
|
|
command,
|
|
cwd=cwd,
|
|
creationflags=creation_flags,
|
|
shell=shell
|
|
)
|
|
|
|
if wait:
|
|
process.wait()
|
|
|
|
return process.pid
|