如何正确停止phantomjs执行

时间:2014-08-04 01:20:39

标签: python macos selenium selenium-webdriver 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

我该如何关闭驱动程序?

7 个答案:

答案 0 :(得分:45)

截至2016年7月,driver.close()driver.quit()对我来说还不够。这导致node进程终止,但不会导致它产生的phantomjs子进程。

在对this GitHub issue的讨论之后,对我有用的唯一解决方案就是运行:

import signal

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

答案 1 :(得分:21)

请注意,如果您的计算机上有多个线程/进程启动PhantomJS,这显然会造成麻烦。

我看到有几个人在讨论同样的问题,但对我来说,最简单的解决方法/黑客是通过Python在您调用driver.close()driver.quit()之后从命令行执行以下操作:

pgrep phantomjs | xargs kill

答案 2 :(得分:18)

不保证.close()方法释放与驱动程序实例关联的所有资源。请注意,这些资源包括但不限于驱动程序可执行文件(在本例中为PhantomJS)。 .quit()方法旨在释放驱动程序的所有资源,包括退出可执行进程。

答案 3 :(得分:6)

I was having a similar issue on Windows machine. I had no luck with either

driver.close()

or

driver.quit()

actually closing out of the PhantomJS window, but when I used both, the PhantomJS window finally closed and exited properly.

driver.close()
driver.quit()

答案 4 :(得分:2)

driver.quit()在Windows 10上对我不起作用,所以我在调用driver.close()后立即添加以下行:

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

,其中

/f = force
/im = by image name

由于这是仅限Windows的解决方案,因此仅在os.name == 'nt'

执行时才是明智之举

答案 5 :(得分:2)

您使用的操作系统是什么?如果您使用POSIX OS,我认为它与下一个的情况相对应。

我创建了拉取请求,但它拒绝了。 https://github.com/SeleniumHQ/selenium/pull/2244

但我认为显然是正确的。因此,我发出了一个问题。 https://github.com/SeleniumHQ/selenium/issues/2272

此问题的根本原因是ghost驱动程序模式phatmojs的结束方法不正确。最后并没有使用ghost驱动模式phantomjs的关闭API。

对于在Linux或OSX上以npm安装的phantomjs, 一个selenium调用Popen for phantomjs,一个phantomjs为lib / phantomjs.js调用spawn。此时,selenium是父母,phantomjs是孩子,lib / phantomjs.js是孙子。

你在父(selenium)中调用quit(),它将SIGTERM发送给子(phantomjs)。和一个孩子(phantomjs)在孩子的SIGTERM处理函数中将SIGTERM发送给孙子(lib / phantomjs.js)。

当孩子将SIGKILL发送给孩子之前,孙子将是僵尸,然后孩子将SIGTERM发送给孙子。

使用ghost驱动程序模式shutdown api关闭此拉取请求ttps://github.com/SeleniumHQ/selenium/pull/2244。

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

答案 6 :(得分:0)

我还使用selenium在我的mac上运行python脚本来使用PhantomJS作为webdriver来做一些事情。

当我的测试运行时,这里有三个注意事项:

$ 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

注意第二列是进程号,第三列是进程父进程号。 我的测试脚本是父级。有一个节点进程将我的测试脚本作为父节点,然后有另一个PhantomJS进程,其父节点是节点进程。不要问我为什么会有两个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的进程,但它使其子进入孤儿状态。我不知道这是否是故意的。如果它不是故意的,那么我认为没有适当的'在代码中退出此过程的方法。

因此,在kill -9 28090

之后,我会使用相当于driver.quit()的语言