简体   繁体   English

无法使用process.kill()或process.terminate()或os.kill()或使用psutil来杀死Python子进程

[英]Unable to kill Python subprocess using process.kill() or process.terminate() or os.kill() or using psutil

Using python, I am starting two subprocesses in parallel. 使用python,我并行启动两个子进程。 One is an HTTP Server, while other is an execution of another program(CustomSimpleHTTPServer.py, which is a python script generated by selenium IDE plugin to open firefox, navigate to a website and do some interactions). 一个是HTTP服务器,而另一个是另一个程序的执行(CustomSimpleHTTPServer.py,这是一个由selenium IDE插件生成的python脚本,用于打开firefox,导航到一个网站并进行一些交互)。 On the other hand, I want to stop execution of the first subprocess(the HTTP Server) when the second subprocess is finished executing. 另一方面,我想在第二个子进程完成执行时停止执行第一个子进程(HTTP Server)。

The logic of my code is that the selenium script will open a website. 我的代码的逻辑是selenium脚本将打开一个网站。 The website will automatically make a few GET calls to my HTTP Server. 该网站将自动对我的HTTP服务器进行几次GET调用。 After the selenium script is finished executing, the HTTP Server is supposed to be closed so that it can log all the captured requests in a file. 在执行selenium脚本之后,应该关闭HTTP Server,以便它可以将所有捕获的请求记录在文件中。

Here is my main Python code: 这是我的主要Python代码:

class Myclass(object):

HTTPSERVERPROCESS = ""

    def startHTTPServer(self):
        print "********HTTP Server started*********"
        try:
            self.HTTPSERVERPROCESS=subprocess.Popen('python CustomSimpleHTTPServer.py', \
                            shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
        except Exception as e:
            print "Exception captured while starting HTTP Server process: %s\n" % e

    def startNavigatingFromBrowser(self):
        print "********Opening firefox to start navigation*********"
        try:
            process=subprocess.Popen('python navigationScript.py', \
                            shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            process.communicate()
            process.wait()
        except Exception as e:
            print "Exception captured starting Browser Navigation process : %s\n" % e
        try:
            if process.returncode==0:
                print "HTTPSERVEPROCESS value: %s" % self.HTTPSERVERPROCESS.returncode
                print self.HTTPSERVERPROCESS
                #self.HTTPSERVERPROCESS.kill()
                #self.HTTPSERVERPROCESS.terminate()
                #self.kill(self.HTTPSERVERPROCESS.pid)
        except Exception as e:
            print "Exception captured while killing HTTP Server process : %s\n" % e

    def kill(self,proc_pid):
        process = psutil.Process(proc_pid)
        for proc in process.get_children(recursive=True):
            proc.kill()
        process.kill()

    def startCapture(self):
        print "********Starting Parallel execution of Server initiation and firefox navigation script*********"
        t1 = threading.Thread(target=self.startHTTPServer())
        t2 = threading.Thread(target=self.startNavigatingFromBrowser())
        t1.start()
        t2.start()
        t2.join()

Note: Execution starts by calling startCapture() 注意:执行从调用startCapture()开始

Here is the code for CustomSimpleHTTPServer.py, which is supposed to write the captured requests to logfile.txt upon termination: 以下是CustomSimpleHTTPServer.py的代码,它应该在终止时将捕获的请求写入logfile.txt:

import SimpleHTTPServer
import SocketServer

PORT = 5555

class MyHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    log_file = open('logfile.txt', 'w')
    def log_message(self, format, *args):
        self.log_file.write("%s - - [%s] %s\n" %
                        (self.client_address[0],
                         self.log_date_time_string(),
                         format%args))

Handler = MyHTTPHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
httpd.serve_forever()

When I use self.HTTPSERVERPROCESS.kill() or self.HTTPSERVERPROCESS.terminate() or os.kill(), I get following in my terminal upon running the main Python code 当我使用self.HTTPSERVERPROCESS.kill()或self.HTTPSERVERPROCESS.terminate()或os.kill()时,我在运行主Python代码时在终端中得到关注

********Starting Parallel execution of Server initiation and firefox navigation script*********
********SimpleHTTPServer started*********
********Opening firefox to start navigation*********
HTTPSERVEPROCESS value: <subprocess.Popen object at 0x1080f8410>
2459
Exception captured while killing HTTP Server process : [Errno 3] No such process


Process finished with exit code 0

And when I use self.kill(self.HTTPSERVERPROCESS.pid), I get following in my terminal upon running the main Python code 当我使用self.kill(self.HTTPSERVERPROCESS.pid)时,我在运行主Python代码时在终端中得到关注

********Starting Parallel execution of Server initiation and firefox navigation script*********
********SimpleHTTPServer started*********
********Opening firefox to start navigation*********
HTTPSERVEPROCESS value: <subprocess.Popen object at 0x1080f8410>
2459
Exception captured while killing HTTP Server process : 'Process' object has no attribute 'get_children'


Process finished with exit code 0

Neither of the following 3 are able to kill the HTTPServer process: 以下3个都无法终止HTTPServer进程:

self.HTTPSERVERPROCESS.kill()
self.HTTPSERVERPROCESS.terminate()
self.kill(self.HTTPSERVERPROCESS.pid)

I know that CustomSimpleHTTPServer.py is correct because when I run it seperately and manually browse to the website, and then manually terminate the CustomSimpleHTTPServer.py script by hitting CTRL-c in terminal, the logs are populated in logfle.txt. 我知道CustomSimpleHTTPServer.py是正确的,因为当我单独运行它并手动浏览到网站,然后通过点击终端中的CTRL-c手动终止CustomSimpleHTTPServer.py脚本时,日志将填充在logfle.txt中。

What changes do I make to my code so that it works properly and logs are populated? 我对我的代码做了哪些更改,以使其正常工作并填充日志?

You should just use os.kill() to signal processes: 你应该只使用os.kill()来表示进程:

import os
import signal
...
os.kill(the_pid, signal.SIGTERM)   # usually kills processes
os.kill(the_pid, signal.SIGKILL)   # should always kill a process

Also, if you kill the parent process it also usually kills the children. 此外,如果您杀死父进程,它通常也会杀死孩子。

Update: 更新:

I made two small changes to the Server program: 我对Server程序做了两处小改动:

  • Add a call to self.log_file.flush() to make sure log entries are flushed out to the log file. 添加对self.log_file.flush()的调用以确保将日志条目刷新到日志文件中。
  • Override allow_reuse_address so that you can reuse the same address shortly after terminating the server. 覆盖allow_reuse_address以便在终止服务器后立即重用相同的地址。 (See this SO question ) (见这个问题

File Server : 文件Server

#!/usr/bin/env python

import SimpleHTTPServer
import SocketServer
PORT = 5555

class MyServer(SocketServer.TCPServer):
    allow_reuse_address = True

class MyHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    log_file = open('logfile.txt', 'w')
    def log_message(self, format, *args):
        self.log_file.write("%s - - [%s] %s\n" %
                        (self.client_address[0],
                         self.log_date_time_string(),
                         format%args))
        self.log_file.flush()

Handler = MyHTTPHandler
httpd = MyServer(("", PORT), Handler)
httpd.serve_forever()

Here is an simple navigation program (file Navigate ): 这是一个简单的导航程序(文件Navigate ):

#!/usr/bin/env python

import requests
import time

URL = "http://localhost:5555/"

def main():
  for x in range(5):
    print "x =", x
    r = requests.get(URL + "asd")
    time.sleep(1)
  print "Quitting"

main()

And here is the main program: 以下是主要计划:

#!/usr/bin/env python

import os
import subprocess
import signal

def main():
  # start web server
  web = subprocess.Popen(["./Server"])
  print "web server pid:", web.pid

  # start navigator
  nav = subprocess.Popen(["./Navigate"])
  print "nav pid: ", nav.pid

  # wait for nav to exit
  nav.wait()
  print "done waiting for nav"
  print "killing web server"
  os.kill(web.pid, signal.SIGTERM )
  web.wait()
  print "server terminated"

main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM