1
3

Python Selenium with文を使ってwebdriverの閉じ漏れをなくす

Posted at

はじめに

本記事のコードは以下の環境で検証しています。
※OSやバージョンが異なる場合、挙動が変わる可能性があります。

OS: Windows10
Python: 3.12.2
selenium: 4.17.2

ブラウザはChromeで記載していますが、Firefoxなど別ブラウザでも同様の対策ができるようです。

driverの生成の仕方でwebdriverが残存することがある

driverを生成する方法によってはdriverを閉じることが出来ず、プロセスが残ってしまうことがあります。
これによりメモリなどを無駄に使ってしまい、リソースを圧迫し他のプログラムに影響を与えてしまうことがあります。
こういったwebdriverの閉じ漏れ、対策方法についてまとめていきます。

driverが残存するおそれのある書き方

それではいきなり、driverが残存するおそれのある書き方を見てみましょう。

from selenium import webdriver


driver = webdriver.Chrome()

driver.get("http://selenium.dev")

driver.quit()

このコード実はseleniumの公式サイトに記載された記述方法です...

どういう場合にdriverの閉じ漏れが発生するのか

まずはdriverを閉じる方法を確認します。
driverを閉じる方法としては

driver.quit()

このコードが実行されることによりdriverが閉じられます。

そのため
driver.quit()を記載しなかった場合
driver.quit()を記載していたが、driverの操作中にエラーが発生し実行されなかった場合
にdriverが残存してしまいます。

閉じ漏れの発生するコード例

実務でコードを書くときはエラーを検知できるよう、エラーハンドリングしていると思います。
driverが残存するおそれのある書き方のコードをtry except で囲ってエラーハンドリングしてみましょう。
driver.get を存在しないURLに変更しエラーを起こすようにしています。
これにより
driver.quit()が実行されずにexceptへ行ってしまい、driverが閉じられません。

from selenium import webdriver

try:
    driver = webdriver.Chrome()
    # 存在しないURLを指定してエラーを起こす
    driver.get("http://not-exists.selenium.dev") # ここでエラーになってexceptに行く
    driver.quit() # ここを通らないため、driverが閉じない
except Exception as e:
    # エラー通知代わりのプリント文
    print(e)

いくらシンプルなコードでも、通信の問題などでエラーが発生してしまう可能性もあるため、こういったdriverの生成、エラーハンドリングは避けるべきです。

閉じ漏れを防ぐdriverの生成方法

driverの生成を以下のように変更することで防ぐことが出来ます。
他にもfinallyでdriverを閉じるという方法もありますが
これがdriver生成のベストプラクティス、これだけ覚えればいい気がします。

from selenium import webdriver

try:
    with webdriver.Chrome() as driver:
        driver.get("http://not-exists.selenium.dev")
except Exception as e:
    print(e)

このようにwith文で書くことにより
エラーが有っても無くてもwithブロックを抜けたときに自動的にdriver.quit()が呼び出されるようになります。
なのでdriver.quit()を明示的に書く必要が無くなります。

正確に言うと、withブロックを抜けるとクラスの__exit__メソッドが呼び出されます。
そのためseleniumライブラリ selenium/webdriver/remote/webdriver.py内
WebDriverクラスの__exit__メソッドのself.quit()が実行されています。

(おまけ)

finallyでdriverを閉じる

with文での書き方だけ覚えればいい気がしますが
finallyでエラーが有っても無くてもdriver.quit()する方法です。

from selenium import webdriver

try:
    driver = webdriver.Chrome()
    # 存在しないURLを指定してエラーを起こす
    driver.get("http://not-exists.selenium.dev") # ここでエラーになってexceptに行く
except Exception as e:
    # エラー通知代わりのプリント文
    print(e)
finally: # finallyはエラーが有っても無くても実行される
    driver.quit()

Pythonのコード上で chromedriver.exe の残存を確認

プロセスに"chromedriver.exe"が存在するかはタスクマネージャーを見れば分かりますが
以下のようなコードで、Pythonのコード上で確認することが出来ます。

※psutilというライブラリを使用しているのでpip install psutilでインストールが必要です。

import psutil

exists_chromedriver = False
for proc in psutil.process_iter():
    if proc.name() == "chromedriver.exe":
        exists_chromedriver = True
        break

if exists_chromedriver:
    print("chromedriver.exe プロセスが存在します。")
else:
    print("chromedriver.exe プロセスが存在しません。")

実際に動作させてみると

with文ではない記述
import psutil
from selenium import webdriver

try:
    driver = webdriver.Chrome()
    driver.get("http://not-exists.selenium.dev")
    driver.quit()
except Exception as e:
    print(e)

exists_chromedriver = False
for proc in psutil.process_iter():
    if proc.name() == "chromedriver.exe":
        exists_chromedriver = True
        break

if exists_chromedriver:
    print("chromedriver.exe プロセスが存在します。")
else:
    print("chromedriver.exe プロセスが存在しません。")

# >>> chromedriver.exe プロセスが存在します。

with文で書いていない方は、driverが残存し

with文での記述
import psutil
from selenium import webdriver

try:
    with webdriver.Chrome() as driver: # withブロックを抜けるとquit()が呼び出される
        driver.get("http://not-exists.selenium.dev")
except Exception as e:
    print(e)

exists_chromedriver = False
for proc in psutil.process_iter():
    if proc.name() == "chromedriver.exe":
        exists_chromedriver = True
        break

if exists_chromedriver:
    print("chromedriver.exe プロセスが存在します。")
else:
    print("chromedriver.exe プロセスが存在しません。")

# >>> chromedriver.exe プロセスが存在しません。

with文で書いた方は、きちんとdriverが閉じられていることが確認できます。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3