web-dev-qa-db-ja.com

phantomjsの実行を適切に停止する方法

Pythonで以下を使用してphantomjsを開始して閉じます。

from Selenium import webdriver    
driver = webdriver.PhantomJS()
driver.get(url)
html_doc = driver.page_source
driver.close()

それでも、スクリプトの実行が終了した後、Mac Activity Monitorでphantomjsのインスタンスを見つけます。実際、スクリプトを実行するたびに、新しいプロセスphantomjsが作成されます。

ドライバーを閉じる方法は?

38
CptNemo

.close()メソッドは、ドライバーインスタンスに関連付けられたすべてのリソースを解放することを保証しません。これらのリソースには、ドライバーの実行可能ファイル(この場合はPhantomJS)が含まれますが、これに限定されないことに注意してください。 .quit()メソッドは、実行可能プロセスの終了を含む、ドライバーのすべてのリソースを解放するように設計されています。

18
JimEvans

2016年7月の時点では、driver.close()driver.quit()では不十分でした。それはnodeプロセスを強制終了しましたが、それが生成したphantomjs子プロセスは強制終了しませんでした。

このGitHubの問題 に関する議論に続いて、私のために働いた唯一のソリューションは次のように実行することでした:

import signal

driver.service.process.send_signal(signal.SIGTERM) # kill the specific phantomjs child proc
driver.quit()                                      # quit the node proc
45
leekaiinthesky

マシン上でPhantomJSを起動する複数のスレッド/プロセスがある場合、これは明らかに問題を引き起こすことに注意してください。

同じ問題に苦しんでいる人々を見たことがありますが、私にとって最も簡単な回避策/ハックは、コマンドラインからPythonを呼び出した後、driver.close()またはdriver.quit()

pgrep phantomjs | xargs kill
21
whirlwin

Windowsマシンでも同様の問題が発生していました。私も運がなかった

driver.close()

または

driver.quit()

実際にPhantomJSウィンドウを閉じますが、両方を使用すると、PhantomJSウィンドウが最終的に閉じて適切に終了しました。

driver.close()
driver.quit()
6
John H.

driver.quit()はWindows 10では機能しませんでしたので、driver.close()を呼び出した直後に次の行を追加しました。

os.system('taskkill /f /im phantomjs.exe')

どこで

/f = force
/im = by image name

また、これはWindows専用のソリューションであるため、os.name == 'nt'

2
FoxMulder900

使用しているOSは何ですか? POSIX OSを使用している場合、次のケースに対応すると思います。

プルリクエストを作成しましたが、拒否されました。 https://github.com/SeleniumHQ/Selenium/pull/2244

しかし、私は明らかにそれが正しいと思います。したがって、私は問題を発行しました。 https://github.com/SeleniumHQ/Selenium/issues/2272

この問題の根本的な原因は、ゴーストドライバーモードphatmojsの終了方法が正しくないことです。最後にゴーストドライバーモードphantomjsのシャットダウンAPIを使用しません。

LinuxまたはOSXのnpmにインストールしたphantomjsの場合、SeleniumはphantomjsのPopenを呼び出し、phantomjsはlib/phantomjs.jsのspawnを呼び出します。現時点では、Seleniumは親、phantomjsは子、lib/phantomjs.jsは孫です。

親(Selenium)でquit()を呼び出し、SIGTERMを子(phantomjs)に送信します。そして、child(phantomjs)は、子のSIGTERMハンドラー関数でSIGTERMをgrandchild(lib/phantomjs.js)に送信します。

子がSIGTERMを孫に送信する前に親がSIGKILLを子に送信すると、孫はゾンビになります。

このプルリクエストttps://github.com/SeleniumHQ/Selenium/pull/2244は、ゴーストドライバーモードシャットダウンAPIを使用してシャットダウンされます。

 def send_remote_shutdown_command(self):
      super(Service, self).send_remote_shutdown_command()  ## ADD A NEW LINE HERE
      if self._cookie_temp_file:
          os.close(self._cookie_temp_file_handle)
          os.remove(self._cookie_temp_file)

他の解決策は、「self.process.ternimate()」と「self.process.kill()」の間でスリープします。 ttps://github.com/SeleniumHQ/Selenium/blob/051c8b110a1aec35247cd45fa4db85c6e522cdcb/py/Selenium/webdriver/common/service.py#L151-L153

        self.process.terminate()
        time.sleep(1)  ## ADD A NEW LINE HERE
        self.process.kill()
        self.process.wait()
2
TakesxiSximada

また、pythonスクリプトをSeleniumを使用してMacで実行し、PhantomJSをWebドライバーとして使用して何らかの処理を行います。

テストを実行しているとき、注意すべき3つのプロセスがあります。

_$ ps -ef | grep [p]hantomjs
  501 28085 24925   0  9:03pm ttys002    0:00.34 python test.py
  501 28088 28085   0  9:03pm ttys002    0:00.14 node /usr/local/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
  501 28090 28088   0  9:03pm ttys002    0:00.71 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
_

2番目の列はプロセス番号であり、3番目の列はプロセスの親です。私のテストスクリプトは親です。テストスクリプトを親として持つノードプロセスがあり、そのノードプロセスを親とする別のPhantomJSプロセスがあります。なぜ2つのPhantomJSプロセスがあるのか​​を聞かないでください。

とにかく、私のMacのアクティビティモニターでは、これを見ることができます:

enter image description here

PID番号28090に注意してください。

私のテストがこれを実行し終えると、あなたと同じようにプロセスが動き回ります。まだ実行中のプロセスを確認すると、次のことがわかります。

_$ ps -ef | grep [p]hantomjs
  501 28090     1   0  9:03pm ttys002    0:18.93 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
_

したがって、driver.quit()はPID番号28088のノードプロセスを終了するように見えますが、その子は孤立したままになります。これが意図的なものかどうかはわかりません。意図的でない場合は、コードでこのプロセスを終了する「適切な」方法はないと思います。

したがって、driver.quit()の直後に、あなたの言語の_kill -9 28090_と同等のものを使用します

0
Sebastian