I have a main.py which open a new cmd (subprocess) when another program (test.py, in same directory) is hanged.
To determining test.py is hanged or not, I used latest modified time (os.path.getmtime(test.log)) log file, test.log (test.py is continuously writing lines to this test.log file)
Now I have few things to to:
- when test.py hanged open a new cmd
- in new opened cmd run test.py
- kill cmd when we opened more than 2 cmd
# test.py
import time
print("test.py started...")
time.sleep(1000) # this is so long because it is behaving like test.py is hanged
print("test.py is finished...") # before this line i want to close this terminal
# main.py
import datetime
import shelx
import subprocess
def modified_time():file_date = time.ctime(os.path.getmtime('test.log'))file_date = datetime.datetime.strptime(file_date, "%a %b %d %H:%M:%S %Y")delta = datetime.datetime.now() - file_datet = delta.total_seconds()return divmod(t, 60)[0] # return minutescmd2 = "python test.py"
while(True):if modified_time() >= 2:b = subprocess.Popen(["start", "/wait", "cmd.exe", "/k", cmd2], shell=True)(output, err) = b.communicate()# b.wait()pid_lst.append(b.pid)print(pid_lst)while len(pid_lst) > 2:x = pid_lst.pop(0)#cmd_2 = f"WMIC PROCESS WHERE \"ProcessID={str(x)}\" CALL TERMINATE"cmd_2 = f"taskkill /PID {str(x)} /F"args = shlex.split(cmd_2)try:y = subprocess.Popen(args, shell=False)print("killed ", x)except Exception as e:print(e.args)
Under linux I get back the pid of the shell, and the Python processes survive.
To then get the python code to run without the shell I need to specify the full path name of the python executable:
# main.py
import datetime
import subprocess
import time
import os
import logging
import sysdef modified_time():file_date = time.ctime(os.path.getmtime('test.log'))file_date = datetime.datetime.strptime(file_date, "%a %b %d %H:%M:%S %Y")delta = datetime.datetime.now() - file_date# print(f'{file_date=} {datetime.datetime.now()=}')t = delta.total_seconds()return t # divmod(t, 60)[0] # return minutescurrent_dir = os.getcwd()
python_executable = sys.executablecmd2 = f"{python_executable} test.py"logging.basicConfig(filename='test.log', level=logging.DEBUG)
logging.error("test.log touched")b = Nonewhile(True):print(f'{modified_time()=}')time.sleep(.8)if modified_time() >= 2:if b is not None:try:print("killing ", b.pid)b.kill()except Exception as e:print(e.args)breakb = subprocess.Popen(cmd2.split(' '), shell=False)
works with a slightly changed test.py
# test.py
import time
import logging
import oscurrent_dir = os.getcwd()logging.basicConfig(filename=f'{current_dir}/test.log', level=logging.DEBUG)logging.error("test.py started...")time.sleep(1000) # this is so long because it is behaving like test.py is hangedlogging.info("test.py is finished...") # before this line i want to close this terminal
I also made sure the log file gets touched from the launching main.py. I didn't understand the list of pid's so I replaced it with an None initialization of b.
Both files are in the same directory. If they are in separate directories I expect some changes are needed.
Variant starting instance of test.py immediately:
# main.py
import datetime
import subprocess
import time
import os
import logging
import sysdef modified_time():file_date = time.ctime(os.path.getmtime('test.log'))file_date = datetime.datetime.strptime(file_date, "%a %b %d %H:%M:%S %Y")delta = datetime.datetime.now() - file_date# print(f'{file_date=} {datetime.datetime.now()=}')t = delta.total_seconds()return t # divmod(t, 60)[0] # return minutescurrent_dir = os.getcwd()
python_executable = sys.executablecmd2 = f"{python_executable} test.py"b = subprocess.Popen(cmd2.split(' '), shell=False)while(True):print(f'{modified_time()=}')time.sleep(.8)if modified_time() >= 2:try:print("killing ", b.pid)b.kill()except Exception as e:print(e.args)breakb = subprocess.Popen(cmd2.split(' '), shell=False)