【发布时间】:2019-03-08 21:49:28
【问题描述】:
我正在尝试从 Python 启动 server to score PMML models in Java。计算完成后,我希望能够关闭该服务器(即终止进程)。我使用的是 Windows 10。但是,我发现它比我想象的更令人困惑。
首先我像这样启动服务器:
p = subprocess.Popen('START /B java -jar openscoring-server-executable-1.4.3.jar',
shell=True)
我让它在后台运行,这样当用户运行脚本时,CMD 窗口就不会出现。为了使这成为可能,我认为shell=True 参数是必要的。
当我尝试使用此行终止进程时:
subprocess.call("TASKKILL /F /PID {pid} /T".format(pid=p.pid))
进程仍在运行。事实上,p.pid 返回的 PID 甚至在任务管理器中都不存在。我在尝试使用this answer 中提供的解决方案时确认了这一点:
def kill(proc_pid):
process = psutil.Process(proc_pid)
for proc in process.children(recursive=True):
proc.kill()
process.kill()
kill(p.pid)
这会返回异常NoSuchProcess: no process found with pid 5280。
我可以通过任务管理器查看分配给我要杀死的进程的 PID:
但我不知道如何在 Python 中找到该 PID 来终止它。我在网站上找到的答案似乎不适用于后台运行的进程。
编辑:
如果我能够使用shell=False 运行命令,我认为这可以解决,但由于START /B,我不知道该怎么做。这会返回一个错误:
p = subprocess.Popen(['START', '/B', 'java', '-jar openscoring-server-executable-1.4.3.jar'])
【问题讨论】:
-
你试过没有
START /B吗? -
@CristiFati 是的,它会打开一个 CMD 窗口,我想避免这种情况。这就是我在命令中引入它的原因。我相信这与我得到的 PID 是对应于创建的 shell 而不是从它启动的进程这一事实有关。我认为这可以通过使用
shell=False来解决,但我不知道使用START /B时是否可以。 -
嗯,我创建了一个虚拟 Java 程序,它有一个无限循环,可以打印一些内容并休眠一秒钟,正常运行(使用
subprocess.Popen),但它没有打开新窗口,而是将其输出重定向到我启动 Python 进程(其父进程)的控制台中。添加START /B时的行为是相同的(并且它也与其父对象分离)。 -
您正在获取
START命令的PID。也许尝试p = subprocess.Popen(['javaw', '-jar openscoring-server-executable-1.4.3.jar'], creationflags=(subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS), close_fds=True)以javaw开头使java 不会产生控制台。其余的让进程独立运行(理论上——我是从谷歌搜索得到的)。 -
@StevenRumbalski,
CREATE_NEW_PROCESS_GROUP对于 javaw.exe 之类的 GUI 进程通常毫无意义。唯一使用进程组的 WinAPI 是GenerateConsoleCtrlEvent,因此程序必须调用AllocConsole或AttachConsole才能使进程组相关。DETACHED_PROCESS对于 GUI 应用程序也毫无意义。其目的是在不分配新控制台的情况下将子控制台与当前控制台分离。
标签: python windows cmd subprocess kill-process