繁体   English   中英

为什么Selenium + Node + PhantomJS在Python脚本结束后仍然运行?

[英]Why Selenium + Node + PhantomJS still running after Python script ends?

我使用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 Notebook上执行代码之后,要测试一下。 过了一会儿,我在我的活动监视器上得到了这个:

在此输入图像描述

还有这个:

在此输入图像描述

即使我添加了一个驱逐舰之后,这些过程仍然会运行:

def __del__(self):
    self.driver.close()    

怎么了? 我真的很感激“为什么会这样”的回答,而不是“做这个”。 为什么我的驱逐舰不工作?

我打开了@forivall链接,看到了Selenium代码。 PhantomJS webdriver有它自己的析构函数(因此使我的多余)。 他们为什么不在这种情况下工作?

__del__()在python中往往不可靠。 你不仅不知道何时会被召唤,你甚至不能保证它会被召唤。 try / finally构造,或(甚至更好)with-blocks(也称为上下文管理器),更可靠。

也就是说,即使使用上下文管理器,我也有类似的问题。 phantomjs进程遍布整个地方。 我通过硒调用phantomjs如下:

from selenium import webdriver
from contextlib import closing
with closing(webdriver.PhantomJS()) as driver:
    do_stuff(driver)

contextlibclosing()函数确保无论发生什么事情都会调用其参数的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)

要么

from selenium import webdriver
driver = webdriver.PhantomJS()
try:
    do_stuff(driver)
finally:
    driver.quit()

(以上两个片段相同)

感谢@ Richard对原始问题的评论,指向我.quit()

截至2016年7月,在讨论此GitHub问题后 ,最佳解决方案是运行:

import signal

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

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

    self.driver = webdriver.PhantomJS()

这将创建一个Web浏览器,然后由Selenium用于运行测试。 每次Selenium运行时,它都会打开一个新的Web浏览器实例,而不是查看是否有可以重新使用的前一个实例。 如果在测试结束时不使用.close,则浏览器将继续在后台运行。

如您所见,多次运行测试会使多个浏览器孤立。

这种情况与Python通常会自动销毁的垃圾收集器有什么区别?

不同之处在于它 Python的域之外创建了一些东西:它正在创建一个新的操作系统级流程。 也许webdriver.PhantomJS应该有自己的__del__ ,它会自行关闭 也许这种行为应该更加强大,但这不是硒开发人员的设计决定,可能是因为大多数其他驱动程序都没有无头(因此很明显窗户是打开的)。

不幸的是, (或非官方)文档都没有很多澄清/最佳实践。 (见下面关于__del__行为的评论)。


链接到源: phantomjs / webdriver.py remote / webdriver.py (superclass)

我也在努力解决同样的问题,我从这个源链接 解决了它。

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

通过使用driver.quit()将在完成程序时终止所有phantomjs进程或使用CTR + C取消程序

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM