技術ブログ

  1. HOME
  2. ブログ
  3. IT技術
  4. 6ステップで出来るOSSでエラーが出た時の調査方法ワークフロー(1)

6ステップで出来るOSSでエラーが出た時の調査方法ワークフロー(1)

こんにちは!PA Labメディアです。
本日はオープンソースソフトウェア(OSS)で問題が出てきた際のデバッグの方法に関しての記事を執筆していきます。OSSに限定して記事を書いていますが、OSSに限らず適用する事ができます。
地味に見えるかもしれませんが、問題が起きた際の調査力はエンジニアにとって非常に重要なスキルで見たことのないエラーを解決出来る能力はどの現場でも求められます。
問題を特定するためには実際には様々な調査方法がありますが、今回は最もシンプルなワークフローエラーが出た際の修正方法、対応方法を簡単に解説していきます。

今回の記事では以下のような方を対象にしております。

  • 「問題が起きたときどのように調査したら良いかわからないエンジニアの方」
  • 「オープンソースを理解して、力を身に着けていきたいエンジニアの方」
  • 「StackOverflowやチャットで質問ばかりしてしまっている方」

本記事は上記のような方を対象にした記事となっています。
結論から話していくと、以下のような流れで調査を進めていきます。

  1. エラー文をきちんと読んで問題を考える
  2. エラー文をコピペで検索
  3. Githubのコードを読む
  4. デバッグをしてみる
  5. ドキュメントを書く
  6. ログを見てみる

今回は実際に現場で発生したエラーに関する調査ワークフローを例にして解説していきます。
Pythonを対象とした例になっていますが、どの言語でも適用可能なので是非最後まで読んでいただければ幸いです。
本記事は2部作となっており、前半の記事となります。

目次

想定状況

  • 言語はPythonで、Seleniumというブラウザ操作のライブラリに関するエラーを対象にする
  • 環境はGoogle Cloud Platform(GCP)のCloud Run上
  • 具体的にはローカル環境では動作するコードがCloud Run上では以下のようなエラーが発生する
2022-06-26 20:58:22.257 JSTTraceback (most recent call last): 
File "/usr/local/lib/python3.10/site-packages/flask/app.py", 
line 2077, in wsgi_app response = self.full_dispatch_request() 
File "/usr/local/lib/python3.10/site-packages/flask/app.py", 
line 1525, in full_dispatch_request rv = self.handle_user_exception(e) 
File "/usr/local/lib/python3.10/site-packages/flask/app.py",
line 1523, in full_dispatch_request rv = self.dispatch_request() 
File "/usr/local/lib/python3.10/site-packages/flask/app.py", 
line 1509, in dispatch_request 
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) 
File "/app/src/execute_selenium.py", line 39, in launch  
frontend_tester.login() File "/app/src/execute_selenium.py", 
line 199, in login self.driver.find_elements_by_css_selector(".execute_selenium")[ 
AttributeError: 'WebDriver' object has no attribute 'find_elements_by_css_selector'

6ステップで出来るOSSでエラーが出た時の調査方法ワークフロー

エラー文をきちんと読んで考える

とても当たり前の事なのですが、実際に現場でタスクが増えて忙しくなってくると何も考えずにコピペで検索してしまったり、その場しのぎで解決策を探してしまう、といった方が多くいるようです。

「エラー文をしっかり読んで、どこに問題がありそうかを考える」という動作を行うことで、着実に技術力が身についていきます。逆に言うと技術力が高いエンジニアは見た事ないエラーでも早い段階で的確な当たりをつけて問題を特定する能力が高いです。

理想としては公式ドキュメントを参照して扱っている技術の基礎知識・概念に関して理解を深めておくと良いですが、なかなか時間が取りづらい方はさっとQiitaなどのまとめの記事を見ても良いかと思います。例えば、今回の場合であればSeleniumの基本的な概念の理解をしておくためにQiitaのまとめ記事10分で理解する Seleniumを読んでおくと良いです。

改めて今回発生したエラー文を再掲します。

2022-06-26 20:58:22.257 JSTTraceback (most recent call last): 
File "/usr/local/lib/python3.10/site-packages/flask/app.py", 
line 2077, in wsgi_app response = self.full_dispatch_request() 
File "/usr/local/lib/python3.10/site-packages/flask/app.py", 
line 1525, in full_dispatch_request rv = self.handle_user_exception(e) 
File "/usr/local/lib/python3.10/site-packages/flask/app.py",
line 1523, in full_dispatch_request rv = self.dispatch_request() 
File "/usr/local/lib/python3.10/site-packages/flask/app.py",
line 1509, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) 
File "/app/src/execute_selenium.py", line 39, in launch  frontend_tester.login() 
File "/app/src/execute_selenium.py", line 199, in login self.driver.find_elements_by_css_selector(".execute_selenium")[ 
AttributeError: 'WebDriver' object has no attribute 'find_elements_by_css_selector'

今回の問題の肝となっている箇所はAttributeError: ‘WebDriver’ object has no attribute ‘find_elements_by_css_selector’という箇所です。WebDriverというクラスは私が作成したクラスではなくてPyPIで配布されているライブラリ、Seleniumの中で定義されているクラスになります。

ただし、ローカル上のコードではそのまま動作していたコードなので、ローカル環境と実行環境(GCP)の中でなにか差がありそうです。具体的にはバージョンが違う事によるエラーなどが考えられそうなので、その仮説を元に調査をしていきます。

エラー文をコピペで検索

それでは、次はエラー文をコピペして検索を行っていきます。ある程度知名度のあるライブラリであれば、似ている問題の解決策がすでにネットで投稿されている可能性があります。

長い検索クエリの場合は重要な箇所だけを抽出して検索したほうが探している記事が見つかる可能性が高いです。例えば今回であれば以下のような検索クエリになります。

 AttributeError: 'WebDriver' object has no attribute 'find_elements_by_css_selector`

特に探しておいた方が良いサイトはエンジニアリングの技術系だとstackoverflowGitHubが挙げられ、統計やデータ分析であればstats.stackexchange(統計版のstackoverflow)が良いと思います。
また公式ドキュメントのF&Aを見ておくのも信頼度が高い情報源ですので、参考にしてみる事がおすすめです。今回であればこちらのページになります。

解決策がすでにどこかで挙げられている場合は解説もセットで挙げられているケースが多いと思うので、理解をした上で解決策を試してみる、というのがよくある一般的なエラーの解決方法になります。

今回は似たようなエラーを見つける事ができなかったので、より詳しく見ていく必要があります。

Githubのコードを読む

Githubには抵抗がある方が多いようで、Gitを業務内で日常的に扱っている方でもGithubを見た事がない、という方が多いようです。最近のOSSの文化が進んできた事もあり、大体のOSSライブラリはGithubでソースコードを確認する事ができます。ソースコードは最も正しい情報源の一つなので、これを確認しない手立てはありません。

今回はもともと立てていた仮説「バージョンが違う事が原因で起きているエラー」という事を踏まえて、コードを見ていきましょう。Seleniumのコードはseleniumのリポジトリのpyディレクトリ以下にありそうです。ライブラリの中を見ていくときはどこを見ていくかわからない、という方も多いとは思いますが、ライブラリ名(今回であればselenium)、もしくはsrcのような名前のディレクトリに入っているケースが多いかと思います。今回はselenium以下のディレクトリにありそうです。

今回起きていたエラーはWebDriverクラスだったので、webdriverを選択していきます。

また今回はChromeベースのWebDriverを使用していたので、chromeを選択していきます。

さらに見ていくと、webdriver.pyがWebDriverのクラスについて言及していそうです。

ようやくWebDriverのクラスにたどり着く事ができました。ただし、ここではもともと問題になっていたfind_elements_by_css_selectorのメソッドが存在していなさそうです。そのため、もう少し深堀りをして見ていく必要があるので、継承元のクラスであるChrominumDriverを見ていきましょう。

余談ですが、SourceGraphと呼ばれるChromeの拡張機能を導入することで対象クラスを選択して、`Go to definition`をクリックする事でその定義元まで簡単にジャンプする事ができます。

ここでも対象メソッドfind_elements_by_css_selectorが見つからなかったのですが、ChromiumDriverもまたRemoteDriverという継承元を持っているようですので更に深堀りをしていきましょう。

更に見ていくと、このRemoteDriverは元々別のWebDriverというクラスからできていたようです。どうやらこのクラスが対象メソッドを持っているはずのクラスですが、最新版のコードでは対象メソッドが存在していないようです。

ここまで確認が出来ると「バージョンがアップデートされた事により、対象メソッドがなくなっている」というエラー内容が推測出来そうです。Gitには昔のコミットが見る事ができる機能があるので、念のため以前のバージョンのライブラリには対象メソッドがあったかどうかを確認してみましょう。

今は最新版のコードを確認しているので、以前のコードを確認しにいきましょう。 今回はTagsという所でselenium-3.141.0を選択すると、対象バージョンのコードに切り替わります。

元々想定していた3.141.0のバージョンでは対象メソッドが存在していることが確認できました。


そのため今回は同じDockerfileを使用していても何らかの手違いで違うバージョンのライブラリを使用していそう、という事が確認できました。
後半に続きます。

まとめ

今回の記事ではエラーに関するアプローチを解説していきました。エンジニアであればどの職種でも問題解決力は問われる場面は多いので、見たことないエラーに対してもコピペだけで済まさずに、きちんと考えた上で解決を図っていくことで技術力向上につなげながら日々の業務を行っていく事ができます。


PA Labでは「AIを用いた自動化×サービス開発」の専門家として活動をしています。高度なデータ分析からシステム開発まで一貫したサービス提供を行っており、特に機械学習やディープラーニングを中心としたビジネス促進を得意としております。

無料で分析設計/データ活用に関するご相談も実施中なので、ご相談があればお問い合わせまで。

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

関連記事