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

时间:2013-09-25 17:12:30

标签: python node.js selenium garbage-collection phantomjs

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

enter image description here

而且:

enter image description here

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

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

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

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

5 个答案:

答案 0 :(得分:3)

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

也就是说,即使使用上下文管理器,我也有类似的问题。 phantomjs进程遍布整个地方。我通过硒调用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)

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

(以上两个片段相同)

归功于@ Richard对原始问题的评论,指出我.quit()

答案 1 :(得分:1)

截至2016年7月,在对this GitHub issue的讨论之后,最佳解决方案是运行:

import signal

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

而不是driver.close()。只需运行driver.quit()即可终止node进程,但不会终止它产生的phantomjs子进程。

答案 2 :(得分:0)

    self.driver = webdriver.PhantomJS()

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

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

答案 3 :(得分:0)

  

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

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

不幸的是,the selenium (or unofficial) documentation对此都没有太多的澄清/最佳做法。 (请参阅以下关于__del__行为的评论)。


指向来源的链接: phantomjs/webdriver.py remote/webdriver.py(超类)

答案 4 :(得分:0)

我也在努力解决同样的问题,而且this source link 解决了

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

使用 driver.quit()会在完成程序时终止所有phantomjs进程或使用 CTR + C

取消程序