为什么硒+;节点+;PhantomJS在Python脚本结束后仍在运行?

为什么硒+;节点+;PhantomJS在Python脚本结束后仍在运行?,python,node.js,selenium,garbage-collection,phantomjs,Python,Node.js,Selenium,Garbage Collection,Phantomjs,Im使用PhantomJS收集关于Html页面的数据。我的代码是这样的: from selenium import webdriver class PageElements(): def __init__(self, url): self.driver = webdriver.PhantomJS() self.driver.get(url) self.elements, self.attribute_types = self._load

Im使用PhantomJS收集关于Html页面的数据。我的代码是这样的:

from selenium import webdriver

class PageElements():

    def __init__(self, url):
        self.driver = webdriver.PhantomJS()
        self.driver.get(url)
        self.elements, self.attribute_types = self._load_elements(self.driver)

    def _load_elements(self, self.driver)
        """"This is not relevant"""
所以,有时候在我在IPython笔记本上执行代码之后,我会测试一些东西。过了一会儿,我在活动监视器上看到:

这是:

即使我添加了销毁程序,进程仍会运行,如:

def __del__(self):
    self.driver.close()    
发生了什么事?我真的很想得到一个“为什么会这样”的答案,而不是一个“做这个”的答案。为什么我的驱逐舰坏了

我打开@forival链接,看到了Selenium代码。它有自己的析构函数(这样我的就多余了)。他们为什么不在这个案子里工作

    self.driver = webdriver.PhantomJS()
这将创建一个web浏览器,然后由Selenium使用该浏览器来运行测试。每次Selenium运行时,它都会打开一个新的web浏览器实例,而不是查看是否有以前的实例可以重复使用。如果不使用。在测试结束时关闭,则浏览器将继续在后台运行

如您所见,多次运行测试会使多个浏览器处于孤立状态

这种情况与Python通常使用垃圾收集器自动销毁的对象有什么区别

不同之处在于,它在Python领域之外创建了一些东西:它在创建一个新的OS级进程。也许
webdriver.PhantomJS
应该有自己的
\uu del\uuu
可以自动关闭也许行为应该更健壮,但这不是selenium开发人员所采用的设计决策,可能是因为大多数其他驱动程序都不是无头的(因此很明显,窗口是打开的)

不幸的是,双方对此都没有太多的澄清/最佳实践。(请参见下面关于行为的评论)


链接到来源: (超类)

\uu del\uu()
在python中往往不可靠。你不仅不知道它什么时候会被调用,你甚至不能保证它会被调用。try/finally构造,或者(甚至更好)使用块(也称为上下文管理器),更加可靠

也就是说,即使使用上下文管理器,我也有类似的问题。phantomjs进程到处都在运行。我通过selenium调用phantomjs,如下所示:

from selenium import webdriver
from contextlib import closing
with closing(webdriver.PhantomJS()) as driver:
    do_stuff(driver)
contextlib
closing()
函数确保其参数的
close()
方法在任何情况下都会被调用,但事实证明,
driver.close()
虽然可用,但却是清理webdriver会话的错误方法
driver.quit()
是正确的清理方法。因此,请执行以下操作之一,而不是上述操作:

from selenium import webdriver
from contextlib import contextmanager

@contextmanager
def quitting(quitter):
    try:
        yield quitter
    finally:
        quitter.quit()

with quitting(webdriver.PhantomJS()) as driver:
    do_stuff(driver)

(以上两个片段是等效的)


值得赞扬的是@Richard对原始问题的评论,他将我引向了
.quit()

我也在为同样的问题苦苦挣扎,我解决了它

通过将selenium/webdriver/phantomjs/service.py中的self.process.kill()替换为self.process.send_signal(signal.SIGTERM)


通过使用driver.quit()将在完成程序时终止phantomjs的所有进程,或从2016年7月起使用CTR+C取消程序,在讨论之后,最好的解决方案是运行:

import signal

driver.service.process.send_signal(signal.SIGTERM)
driver.quit()

而不是
driver.close()
。只要运行
driver.quit()
就会杀死
节点
进程,但不会杀死它产生的
phantomjs
子进程。

我明白了。我想知道的是为什么会发生这种事,这很奇怪。我编辑了我的问题。PhantomJS的Selenium Webdriver在实现中有其析构函数。但它也不起作用。我已经有一段时间没有玩过
\uu del\uu
,结果它有一些边缘案例:。如果selenium python api支持上下文管理器的使用,那么它可能会更好(
\uuuuuuuuuuuuuuuuu进入
\uuuuuuuuu退出
与…作为:
。使用上下文管理器会要求您重新组织代码,但这样会更好。嗯,我上周遭到了否决票。请添加一条评论,说明如何改进我的答案,或者它可能是不正确的。代码是否在结束之前退出,可能是由于uncaught异常?没有。在析构函数中添加了一个打印“exit”,并且它已经被执行。查看此页面。似乎phantomJS支持可能已被删除(如该页面上所建议的)。此外,我注意到该页面上的代码使用的是.quit(),而不是.close()-在代码期间是否打开了多个浏览器?如果是这样的话,.close()将关闭当前窗口,但并非所有打开的窗口..quit()将退出当前驱动程序。尝试编辑第二个代码示例以删除额外的“)”for
driver=webdriver.PhantomJS())
,但编辑需要6个字符或更多。
import signal

driver.service.process.send_signal(signal.SIGTERM)
driver.quit()