3

I have a Python script that runs all day long checking time every 60 seconds so it can start/end tasks (other python scripts) at specific periods of the day.

This script is running almost all ok. Tasks are starting at the right time and being open over a new cmd window so the main script can keep running and sampling the time. The only problem is that it just won't kill the tasks.

import os
import time
import signal
import subprocess
import ctypes


freq = 60 # sampling frequency in seconds

while True:    
    print 'Sampling time...'
    now = int(time.time())

    #initialize the task.. lets say 8:30am
    if ( time.strftime("%H:%M", time.localtime(now)) == '08:30'):
        # The following method is used so python opens another cmd window and keeps original script running and sampling time 
        pro = subprocess.Popen(["start", "cmd", "/k", "python python-task.py"], shell=True)

    # kill process attempts.. lets say 11:40am
    if ( time.strftime("%H:%M", time.localtime(now)) == '11:40'):
        pro.kill()    #not working - nothing happens

        pro.terminate()    #not working - nothing happens

        os.kill(pro.pid, signal.SIGINT) #not working - windows error 5 access denied

        # Kill the process using ctypes - not working - nothing happens
        ctypes.windll.kernel32.TerminateProcess(int(pro._handle), -1)

        # Kill process using windows taskkill - nothing happens
        os.popen('TASKKILL /PID '+str(pro.pid)+' /F')

    time.sleep(freq)

Important Note: the task script python-task.py will run indefinitely. That's exactly why I need to be able to "force" kill it at a certain time while it still running.

Any clues? What am I doing wrong? How to kill it?

Sarchophagi
  • 377
  • 2
  • 5
  • 20
  • Are you running the main script as admin. If not that might enable killing python-task.py processes. The latter could also be configured to check for existence of a certain file and exit if that file exists. Then the main script could create that file to cause the python-task.py process to stop. There could be one such file for all python-task.py processes or a unique one for each in which case its name could be passed as an argument and the main script would have to keep track of those names. –  Jul 27 '15 at 23:47
  • @TrisNefzger I've read about the file solution but it would be way better if I can solve this just dealing with the kill-process and not editing python-task.py files. How to grant I'm running the main script as admin? What kill method should I use? – Sarchophagi Jul 28 '15 at 00:06
  • afaik windows does not have this abillity ... open the task manager ... select the task and kill it from there ... – Joran Beasley Jul 28 '15 at 00:25
  • oh I lied maybe http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/ – Joran Beasley Jul 28 '15 at 00:26
  • 1
    why are you rewriting windows scheduler? – Joran Beasley Jul 28 '15 at 00:27
  • On Windows 7 one can go to Control Panel\All Control Panel Items\User Accounts\Change Your Account Type and select Administrator to be put in the Administrator group. That will allow running applications as Administrator which usually is automatic and can be done manually by right clicking on an application icon and selecting "run as administrator". However, sometimes a process is stuck waiting on a kernel resource and even an administrator cannot stop it - see http://superuser.com/questions/585073/how-to-overcome-access-denied-when-killing-process-in-windows and the links it references. –  Jul 28 '15 at 04:47

1 Answers1

3

You're killing the shell that spawns your sub-process, not your sub-process.

Edit: From the documentation:

The only time you need to specify shell=True on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not need shell=True to run a batch file or console-based executable.

Warning

Passing shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.

So, instead of passing a single string, pass each argument separately in the list, and eschew using the shell. You probably want to use the same executable for the child as for the parent, so it's usually something like:

pro = subprocess.Popen([sys.executable, "python-task.py"])
Patrick Maupin
  • 8,024
  • 2
  • 23
  • 42