2016-08-02 52 views
0

Pythonを使用して、私は2つのサブプロセスを並列に開始しています。 1つはHTTPサーバーで、もう1つは別のプログラム(CustomSimpleHTTPServer.py、これは、Firefoxを開いてWebサイトに移動して相互作用を行うためのselenium IDEプラグインによって生成されたPythonスクリプトです)です。一方、第2のサブプロセスの実行が終了すると、最初のサブプロセス(HTTPサーバー)の実行を停止します。process.kill()またはprocess.terminate()またはos.kill()またはpsutilを使用してPythonサブプロセスを終了できません

私のコードのロジックは、セレンスクリプトがウェブサイトを開くことです。ウェブサイトは自動的に私のHTTPサーバーにいくつかのGET呼び出しを行います。セレンスクリプトの実行が終了すると、HTTP Serverは閉じられたものとみなされ、キャプチャされたすべてのリクエストをファイルに記録できます。

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

注:ここでは

は私のメインのPythonコードで実行は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.HTTPSERVERを使用する場合PROCESS.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)を使用する場合、私は次のように取得しますどちらも、以下の3の

********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 

はHTTPServerのプロセスを強制終了することができますメインのPythonコードを実行している時に、私の端末は:

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

私はそれを実行したときのでCustomSimpleHTTPServer.pyが正確であることを知っています個別に手動でWebサイトを参照し、CTRL-cを押してCustomSimpleHTTPServer.pyスクリプトを手動で終了すると、ログはlogfle.txtに読み込まれます。

コードを正しく変更してログを作成するために、どのような変更を加えましたか?

+0

なぜあなたは 'stdout = subprocess.PIPE'と' stderr = subprocess.PIPE'でCustomHTTPServerを起動していますか?これにより、出力を読み取らなければなりません。私はそれらを/ dev/nullまたはファイルにリダイレクトするだけです。 – ErikR

+0

私はちょうど "" self.HTTPSERVERPROCESS = subprocess.Popen( 'python CustomSimpleHTTPServer.py'、shell = True)を実装する必要がありますか? –

+0

Ok - カスタムサーバーがログファイルを設定しているのがわかります。実際には出力が生成されないかもしれません。 – ErikR

答えて

3

あなただけのプロセスを合図する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() 
+1

これは私のために働いていません。それに応じて質問とコードを更新しました。 –

+0

回答が更新されました。 – ErikR

+0

私のHTTPServerコードをあなたの提案で更新し、os.kill()を実装してプロセスを終了させるだけで問題は解決しました。ありがとう –

関連する問題