質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

21586閲覧

Python Seleniumで処理後コンソールを消してそのままChromeを使用し続ける方法

SnowBallEffect

総合スコア28

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

2クリップ

投稿2020/04/14 03:37

Seleniumを使ってChromeであるサイトに自動ログインしてその処理を終えたら、コンソールを消してそのままChromeを使いたいのですが、やり方は分かりますでしょうか?Pyinstallerで--noconsoleというオプションがあるようですが、処理が終わるまでコンソールは出て欲しいです。 

driver.quit() や driver.close() だとブラウザーも閉じてしまうので、やはり違います。

以下のコードだとドライバを削除するのですが、コンソールは消えないです。

Python

1os.system("taskkill /f /im C:\Python\Driver\chromedriver.exe")

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

taskkill コマンドや chromedriver.exe といったファイル名から、対象の環境は Windows かと御見受け致しますが、この場合 「Python 側のコンソールはスクリプトが終わるまで開き、然し chromedriver や Chrome のコンソールは消したい」 という要件の実現は少々面倒です。具体的には、以下 2 つの対応を行う必要があるかと存じます。

  1. chromedriver の detach オプションを有効にし、 chromedriver プロセスだけを終了させる
  2. 子プロセス生成のどこかの時点で、 親プロセスからのコンソールの継承を断ち切る

1) chromedriver の detach オプションを有効にする

まず、 Selenium (WebDriver) の処理を終了させた後に Chrome を使いたいということですから、 Chrome は生存させたまま chromedriver プロセスに終了してもらう 必要が御座いますが、こちらは単純に、 その目的のための detach というオプションが chormedriver に用意されている ので、これを有効にする ことで実現ができます。

但し、 WebDriver.quit() メソッド を呼ぶと、結局 Chrome のセッションごとすべてを終了させてしまうので、 代わりに Service.stop() メソッドを呼び出し、 chromedriver のみを終了させる ことが肝要です。

python

1from selenium import webdriver 2from selenium.webdriver.chrome.options import Options 3 4options = Options() 5options.add_experimental_option('detach', True) 6 7driver = webdriver.Chrome(options=options) 8 9driver.get('https://teratail.com/') 10 11# do something... 12 13driver.service.stop()

2) 親プロセスからのコンソールの継承を断ち切る

さて、以上の対応で Chrome を生存させたまま、 chromedriver や Python のプロセスだけを終了させることが可能となります。実際、タスクマネージャー等を閲覧すると、 Chrome 以外の関係するプロセスは既に終了していることが確認出来るかと存じます。ところが、これでも 問題としている「コンソール画面」は残ってしまっている はずです (仰っている taskkill コマンドの利用時と同じ結果ですね) 。

これはなぜかというと、 Python が使用していたコンソールを、 chromedriver を経由して継承した Chrome のプロセスがそのまま使用している ことが原因です。

Windows 環境でのコンソールプロセスは、例えば コンソールプロセスのコンソール生成に関する Microsft Docs の記事 に "By default, a console process inherits its parent's console" と記載されている通り、デフォルトでは 子プロセスとして起動されたとき、親プロセスがコンソールを持っていればそのコンソールを継承して動作 します。結果、 Chrome プロセスがコンソールを使い続けている限り、親の Python が使っていたコンソールが解放されず、画面もまた閉じられないという状況が生じ得ます。

この問題に対処するには幾つかの方法が考えられますが、比較的簡単な方法としては次の何れかの方法が良いのではないでしょうか。

2-a) プロセス生成時に CREATE_NO_WINDOW フラグを渡す

まず一つ目としては、 chromedriver プロセスを WebDriver が起動する際、 CREATE_NO_WINDOW フラグを渡す 方法が考えられます。

このプロセス生成時のフラグについては Microsoft Docs の該当ページ を御参照頂くと良いのですが、大雑把に言ってしまうと、 「コンソールアプリケーションをコンソール画面を表示させずに動作させる」 フラグであり、結果的に親とは別の非表示のコンソールを使用する形で実行されるため、Python と同じコンソール画面を使用し続けるような状況を回避することが可能になります。

CREATE_NEW_CONSOLEDETACHED_PROCESS も似た説明で紛らわしいのですが、何れも「(必要であれば) 親プロセスとは別のコンソール画面を開く」だけであり、結局 Chrome の使用するコンソール画面が表示されたまま残り続ける問題は解決しません

但し Windows 環境の場合、このフラグは subprocess.Popen() の引数として 渡すことが可能なのですが、 Selenium が子プロセスを生成する Service.start() の実装はこのように なっており、そのままではフラグを渡すことができません。

ですから、該当の selenium/webdriver/common/service.py を編集するか、あるいは次のようにモンキーパッチを一時的に当て、 creationflags を無理矢理渡す必要が出て参ります。

python

1from subprocess import Popen, CREATE_NO_WINDOW 2 3_original_constructor = Popen.__init__ 4 5def _patched_constructor(*args,**kwargs): 6 kwargs['creationflags'] = CREATE_NO_WINDOW 7 8 return _original_constructor(*args, **kwargs) 9 10Popen.__init__ = _patched_constructor 11 12driver = webdriver.Chrome(options=options) 13 14Popen.__init__ = _original_constructor

2-b) Chrome に enable-logging 起動オプションを与えず、コンソールを使わせない

もう一つの考え方として、 そもそも Chrome をコンソールプロセスとして動作させない 、という考え方も御座います。

普段、単にブラウザとして Chrome を起動した場合、特にコンソールは使用せずコンソール画面も開きませんが、これが chromedriver 経由で起動した場合にコンソールを使用するようになるのは、 chromedriver が Chrome にデフォルトで enable-logging という起動オプションを与え、ログ出力を有効にしている ことが原因です。

幸い、このデフォルトの起動オプションは chromedriver の excludeSwitches オプションで無効化出来ますので、例えば以下のようにするだけでも、 Chrome がコンソールを使用しなくなりコンソール画面が開いたままという状況はやはり回避できるかと存じます。

python

1options.add_experimental_option('excludeSwitches', ['enable-logging']) 2 3driver = webdriver.Chrome(options=options)

但し、これにより Chrome のログ出力機能 全体が無効になってしまいますので、その点は御留意頂く必要が御座います。

2-c) conhost.exe の画面を探して非表示にする

GetConsoleWindow() の存在を知らず、誤った回答となっておりましたので、修正致しました

その他の方法としては、 コンソール画面は conhost.exe という別プロセスによって実現されている のですが、 Python スクリプトが 自身の使用している conhost.exe の画面を探し出し、 ShowWindow() API によって非表示にしてから終了する というやり方も考えられます。

python

1import ctypes 2import subprocess 3 4console_hwnd = ctypes.windll.kernel32.GetConsoleWindow() 5ctypes.windll.user32.ShowWindow(console_hwnd, subprocess.SW_HIDE)

この方法であれば、 スクリプト自身が必要な場合のみに不要となったコンソール画面を非表示とできる メリットが御座いますが、不用意に実行すると、例えば開発作業中に使用していた cmd.exe の画面を意図せずに消してしまい、操作ができなくなるような事故も生じ得ますので、御利用には御注意下さいませ。

投稿2020/04/18 08:47

編集2020/04/18 09:55
argparse

総合スコア1017

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SnowBallEffect

2020/04/20 01:14

argparseさん、 細かい説明と一つだけではなく様々な解決方を教えて頂きありがとうございました。私だけではなく、この問題について色んな人が困っているはずなので、argeparseさんの答えは助けになるはずです。改めてありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問