【问题标题】:Changing a variable name affects the code behavior更改变量名会影响代码行为
【发布时间】:2020-06-09 06:15:38
【问题描述】:

当我运行这段代码时,其中一个 selenium 窗口没有关闭

import multiprocessing

from selenium import webdriver


class Worker:
    def __init__(self):
        self.driver = webdriver.Chrome()

    def run(self):
        self.driver.get('https://www.google.com')


processes = []
for i in range(2):
    worker = Worker()
    process = multiprocessing.Process(target=worker.run)
    process.start()
    processes.append(process)

for any_name in processes:
    any_name.terminate()

但如果我将变量名从 any_name 更改为 worker,那么所有 selenium 窗口都将关闭。为什么会这样?

PS 版本:python 3.7、chromedriver 83、selenium 3.141.0

【问题讨论】:

  • 呵呵,这也是我的复制品。我无法解释为什么,但如果您用于最终for 循环的变量名称与您分配给Worker 的变量名称相同,它只会关闭两个窗口。例如。如果将worker = Worker() 更改为blah = Worker(),则必须将any_name 更改为blah 才能关闭窗口。

标签: python selenium process multiprocessing terminate


【解决方案1】:

这是因为浏览器关闭行为依赖于selenium.webdriver.common.service.Service__del__ 方法使浏览器Windows 退出,并且__del__ 只有在不再引用您的WebDriver 实例时才会被调用。这里是Service.__del__的实现:

    def __del__(self):
        # `subprocess.Popen` doesn't send signal on `__del__`;
        # so we attempt to close the launched process when `__del__`
        # is triggered.
        try:
            self.stop()
        except Exception:
            pass

stop() 方法关闭一切。

现在,变量命名很重要的原因是它会影响程序退出时是否有任何对WebDriver 的引用。当您的第一个 for 循环完成时,worker 仍然在作用域内,它包含对您创建的第二个 Worker 的引用,它包含对 WebDriver 的引用。当您的主程序完成时,它会保持在范围内,这意味着永远不会调用 __del__,并且浏览器窗口不会关闭。

但是,当您在第二个 for 循环中重复使用 worker 时,这意味着不再持有对第二个 Worker 的引用,这意味着内存中没有对 WebDriver 的引用,这意味着__del__ 将被调用并且窗口将关闭。您可以通过在第一个 for 循环之外显式添加 worker = None 来确认此行为。随着这一变化,无论您在第二个循环中使用什么变量名,两个浏览器窗口都会退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 2019-01-19
    相关资源
    最近更新 更多