【问题标题】:How to properly stop phantomjs execution如何正确停止 phantomjs 执行
【发布时间】:2014-09-26 10:49:50
【问题描述】:

我使用以下代码在 Python 中启动并关闭 phantomjs

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

在脚本结束执行后,我仍然在我的 Mac 活动监视器中找到了一个 phantomjs 的实例。实际上,每次我运行脚本时,都会创建一个新进程 phantomjs

我应该如何关闭驱动程序?

【问题讨论】:

  • 无法复制,对我来说它会停留几秒钟然后关闭。
  • 如果你改用driver.quit()会发生什么?

标签: python macos selenium selenium-webdriver phantomjs


【解决方案1】:

截至 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

【讨论】:

  • 这种方法最适合我(截至本评论日期)。我也发现了 Github 问题,但想在这里补充它!
  • +1 这也适用于我。当 GitHub 未解决的问题似乎是 PhantomJS 构建器似乎没有兴趣用他们的脚本解决这个相当大的错误时,这有点令人沮丧。也许这个解决方案可以硬编码到 PhantomJS 脚本本身?
  • 直到现在,我的机器里还有一个叉子炸弹!
  • @leekaiinthesky 但是在 ‍‍driver.quit()driver.close() 我使用它之后,我收到了 SessionManagerReqHand - _cleanupWindowlessSessions - Asynchronous Sessions clean-up phase starting NO 消息。是什么原因我该如何解决这个问题?!
  • @AliHesari 您在此处获得答案的最佳方法是将您的问题与详细信息作为新问题发布在网站上。祝你好运!
【解决方案2】:

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

我见过几个人在同一个问题上苦苦挣扎,但对我来说,最简单的解决方法/hack 是在调用 driver.close()driver.quit() 之后通过 Python 从命令行执行以下命令:

pgrep phantomjs | xargs kill

【讨论】:

  • @Arya 它确实会导致使用 PhantomJS 的任何其他进程/线程出现问题,因此除非您对机器上运行的内容有绝对控制权,否则不应使用此方法。
  • 请参阅 stackoverflow.com/questions/25110624/… 以获取仅杀死所涉及的特定单个 phantomjs 进程而不是所有进程的答案。
  • 如果你要偷工减料,那么你不妨使用killall phantomjs
  • @whirlwin 抱歉,但我不得不对此投反对票,因为大多数新开发人员都会遵循此建议,这反过来会在与其他开发人员的进程和不公平的仇恨的共享机器上造成巨大的问题作为回报。如果结束警告移到开头,我会投票。
  • @Tom 感谢您的反馈!
【解决方案3】:

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

【讨论】:

  • .close().quit() 我都试过了,对我没用
  • @rox 您是否同时使用了关闭和退出?我仍然看到此错误,但现在似乎不是致命的。
【解决方案4】:

我在 Windows 机器上遇到了类似的问题。我都没有运气

driver.close()

driver.quit()

实际上是关闭了 PhantomJS 窗口,但是当我使用两者时,PhantomJS 窗口终于关闭并正常退出了。

driver.close()
driver.quit()

【讨论】:

  • 这也对我有用,我认为它应该被标记为正确的解决方案。它并不优雅,但比提到的其他蛮力方法要好得多。很好的发现。
  • +1 这对我也有用。我比@leekaiinthesky 的解决方案更喜欢这个解决方案,因为我不需要导入另一个库import signal
【解决方案5】:

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

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

在哪里

/f = force
/im = by image name

由于这是一个仅限 Windows 的解决方案,因此最好只在 os.name == 'nt' 时执行

【讨论】:

    【解决方案6】:

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

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

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

    这个问题的根本原因是ghost驱动模式phatmojs的end方法不正确。最后不是不使用ghost驱动模式phantomjs的shutdown API。

    对于您在 Linux 或 OSX 上的 npm 中安装的 phantomjs, phantomjs 的 selenium 调用 Popen,lib/phantomjs.js 的 phantomjs 调用 spawn。此时,一个 selenium 是 parent,一个 phantomjs 是 child,lib/phantomjs.js 是 grandchild。

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

    当父母在孩子向孙子发送 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()
    

    【讨论】:

      【解决方案7】:

      我还有一个 python 脚本在我的 mac 上运行,它使用 selenium 来做一些事情,使用 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 的活动监视器中,我可以看到:

      记下 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多