2

When I try to kill a process in windows with the subprocess.Popen.terminate() or kill() commands, I get an access denied error. I really need a cross-platform way to terminate the process if the file no longer exists (Yes, I know it's not the most elegant way of doing what I'm doing), I don't want to have to use platform calls or import win32api if at all possible.

Also - Once I kill the task, I should be able to just delete the iteration of that portion of the library, no? (I remember reading something about having to use slice if I plan on working on something and modifying it while working on it?)

#/usr/bin/env python
#import sys
import time
import os
import subprocess
import platform

ServerRange = range(7878, 7890)  #Range of ports you want your server to use.
cmd = 'VoiceChatterServer.exe'

#********DO NOT EDIT BELOW THIS LINE*******

def Start_IfConfExist(i):
    if os.path.exists(str(i) + ".conf"):
        Process[i] = subprocess.Popen(" " + cmd + " --config " + str(i) + ".conf", shell=True)

Process = {}

for i in ServerRange:
    Start_IfConfExist(i)

while True:
    for i in ServerRange:
        if os.path.exists(str(i) + ".conf"):
            res = Process[i].poll()
        if not os.path.exists(str(i) + ".conf"):  #This is the problem area
            res = Process[i].terminate()          #This is the problem area.
        if res is not None:
            Start_IfConfExist(i)
            print "\nRestarting: " + str(i) + "\n"
    time.sleep(1)
ThantiK
  • 1,582
  • 4
  • 17
  • 31
  • "I don't want to have to use platform calls or import win32api if at all possible." The documentation says this is impossible. Please check SO for duplicate questions on this exact topic. http://stackoverflow.com/questions/1064335/in-python-2-5-how-do-i-kill-a-subprocess – S.Lott Nov 05 '09 at 18:09
  • @S.Lott: I think he meant "call explicitly the win32 API", in this case Popen.terminate will call it indirectly on Windows, and on Linux it will use Posix. And the link you mention doesn't look like the same problem. – RedGlyph Nov 05 '09 at 18:17
  • @ThantiK: I think the error you get on Windows is due to the fact you specify `shell=True`, do you really need it? If you switch to `shell=False`, don't forget that you have to specify the arguments in a list with the process name as first parameter, in order to run correctly on Linux. – RedGlyph Nov 05 '09 at 18:26
  • Yes, I have to have shell=True in this case. The program I'm calling functions in the shell. Once I set it to false I get all sorts of errors about subprocess failing on __init__ etc... – ThantiK Nov 05 '09 at 18:28
  • @redglyph - calling Popen.terminate() on windows gives me an Access Denied error. It seems like the command is implemented, just not the way I expect it is. (btw, this is on Windows XP) – ThantiK Nov 05 '09 at 18:30
  • @ThantiK: Yes, I understood. It is because with `shell=True`, Popen will launch the shell (here cmd.exe) which will launch your process, and apparently you can't kill the shell like that. With `shell=False` the process is directly launched as a child and you can kill it. The errors you have with `shell=False` might be due to stdout/err/in needing redirection so don't be discouraged too fast, now if you need console interaction I'll understand you can't use that option. – RedGlyph Nov 05 '09 at 19:12

1 Answers1

2

You can easily make a platform independent call by doing something trivial like:

try:
    import win32
    def kill(param):
        # the code from S.Lotts link
except ImportError:
    def kill(param):
        # the unix way

Why this doesn't exist in python by default I don't know, but there are very similar problems in other areas like file change notifications where it really isn't that hard to make a platform independent lib (or at least win+mac+linux). I guess it's open source so you have to fix it yourself :P

boxed
  • 3,895
  • 2
  • 24
  • 26
  • Yeah, it actually kind of baffled me as well. There really should be a standard way of killing a process by passing the PID in win/linux/osx – ThantiK Nov 05 '09 at 18:33
  • The risk with that method, for Windows anyway, is that it will kill the shell but not the child process, unless the sudden lack of console for stdin/out/err makes it crash - that's exactly what I observe on my system. That means the child process will switch to the root Explorer as parent instead of the shell, and possibly still consume and block resources. Conclusion: don't use `shell=True` if the process has to be killed. – RedGlyph Nov 05 '09 at 19:49
  • Again, I have no choice in the matter. The executable I am running cannot be run without a console. If I set shell to false, I get all sorts of python errors about __init_ not happening correctly, etc – ThantiK Nov 05 '09 at 20:14
  • 1
    ```import win32``` doesn't work for me. I had to use ```if os.name == "nt" ``` instead – Maxime Helen Mar 15 '17 at 19:29