【问题标题】:Unable to kill Python subprocess using process.kill() or process.terminate() or os.kill() or using psutil无法使用 process.kill() 或 process.terminate() 或 os.kill() 或使用 psutil 杀死 Python 子进程
【发布时间】:2016-12-08 04:25:08
【问题描述】:

使用 python,我正在并行启动两个子进程。一个是 HTTP 服务器,另一个是另一个程序的执行(CustomSimpleHTTPServer.py,这是一个由 selenium IDE 插件生成的 python 脚本,用于打开 firefox、导航到网站并进行一些交互)。另一方面,我想在第二个子进程执行完毕后停止第一个子进程(HTTP Server)的执行。

我的代码逻辑是 selenium 脚本会打开一个网站。该网站会自动对我的 HTTP 服务器进行一些 GET 调用。 selenium 脚本执行完成后,应该关闭 HTTP 服务器,以便将所有捕获的请求记录在一个文件中。

这是我的主要 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()

注意:通过调用 startCapture() 开始执行

这是 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()

当我使用 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

当我使用 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

以下3个都不能杀死HTTPServer进程:

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

我知道 CustomSimpleHTTPServer.py 是正确的,因为当我单独运行它并手动浏览到网站,然后通过在终端中按 CTRL-c 手动终止 CustomSimpleHTTPServer.py 脚本时,日志将填充到 logfle.txt 中。

我对我的代码进行了哪些更改以使其正常工作并填充日志?

【问题讨论】:

  • 你为什么用stdout=subprocess.PIPEstderr=subprocess.PIPE启动你的CustomHTTPServer?这会迫使您阅读输出。我只是将它们重定向到 /dev/null 或文件。
  • 我应该只实现 "" self.HTTPSERVERPROCESS=subprocess.Popen('python CustomSimpleHTTPServer.py',shell=True) "" 吗?
  • 好的 - 我看到您的自定义服务器设置了一个日志文件,所以实际上它可能不会生成任何输出。

标签: python multithreading selenium


【解决方案1】:

您应该只使用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

另外,如果你杀死父进程,它通常也会杀死子进程。

更新:

我对服务器程序做了两个小改动:

  • 添加对self.log_file.flush() 的调用以确保日志条目 被刷新到日志文件中。
  • 覆盖 allow_reuse_address 以便您可以重复使用 终止服务器后不久的相同地址。 (见this SO question

文件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()

这是一个简单的导航程序(文件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()

这是主程序:

#!/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()

【讨论】:

  • 这对我不起作用。已相应地更新了我的问题和代码。
  • 只需根据您的建议更新我的 HTTPServer 代码并实施 os.kill() 来终止进程即可解决问题。谢谢
猜你喜欢
  • 2012-08-16
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 2011-02-15
相关资源
最近更新 更多