Pythonの「system」とは、コマンドプロンプトで入力できるコマンドを、Pythonで実行するための機能です。例えば、Windowsのバージョン情報や環境変数の表示、ファイルの処理などが行えます。
しかし、現在のPythonではsystemではなく、「subprocess」を使用することが推奨されています。subprocessを活用すると、より高機能なコマンド操作ができるようになるので便利です。そこで本記事では、Pythonのsystemの使い方に加えて、subprocessの活用方法を解説します。
目次
Pythonの「os.system()」関数とは、Pythonからコマンドプロンプトを実行するための機能で、osライブラリに搭載されています。コマンドプロンプトとは、以下のような背景が黒いシンプルな画面で、コマンドを入力することでさまざまな処理を行えます。
上記の画面は、コマンドプロンプトで「time」コマンドを入力して、現在の時刻を表示したものです。Pythonのos.system()関数を以下のように使うと、直接コマンドプロンプトに入力するのではなく、ソースコードから間接的に操作できます。
# 「os」ライブラリをインポートする import os # コマンドプロンプトのコマンドを実行する os.system("コマンド")
まずosライブラリをインポートして、os.system()の引数にコマンドを指定します。正しいコマンドを指定すると、処理が行われて結果が表示されます。コマンドが誤っている場合は、エラーメッセージが表示されるので確認しましょう。os.system()を活用すると、コマンドプロンプトを手動で開いて入力しなくていいので、効率的なコマンド操作が可能となります。
またコマンドプロンプトのようにすべてがテキスト形式で表示されるものを、「CUI(Character User Interface)プログラム」と呼びます。一方、私たちが普段から使用している、画像やボタンなどのグラフィックスで表示するものが、「GUI(Graphical User Interface)プログラム」です。使いやすさの点ではGUIが有利ですが、コマンドプロンプトのようにCUIならではのプログラムもあります。
Pythonのos.system()では、さまざまなコマンドを使うことができます。そのなかでも代表的なコマンドとして、以下の25種類を紹介します。なお、今回紹介するのはWindows PCのコマンドプロンプトを対象としたものなので、一部のコマンドはMacでは動作しません。
Macのコマンドは、基本的には「UNIXコマンド」と同じものになるため、必要に応じてソースコードを書き換えましょう。
「help」は、ヘルプドキュメントを表示するためのコマンドです。コマンドプロンプトで利用できる、すべてのコマンドと機能の概要を確認できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「help」コマンドを実行する # ヘルプドキュメントを表示する os.system("help") // 実行結果
コマンドの意味が分からないときや、必要な機能を備えたコマンドを探したいときに、このhelpコマンドを利用すると便利です。
「ver」は、Windowsのバージョン情報を表示するためのコマンドです。コマンドを入力することで、以下のサンプルコードのようにWindowsのバージョンを確認できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「ver」コマンドを実行する # Windowsのバージョン情報が表示される os.system("ver") // 実行結果
「Windows 10」や「Windows 11」のようなOS名だけではなく、バージョンやビルド番号の詳細も確認できるので便利です。
「systeminfo」は、コンピューターの詳細情報を表示するためのコマンドです。OSの詳細やプロセッサの情報に加えて、BIOSやメモリなどの情報も確認できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「systeminfo」コマンドを実行する # コンピューターの詳細情報が表示される os.system("systeminfo") // 実行結果
コンピューターに関するさまざまな情報が網羅されているので、使用中のデバイスの詳細を確認したいときに便利です。
「set」は、すべての環境変数を表示するためのコマンドです。環境変数とは、プログラムに対して外部からデータを与えて、設定や挙動を変更するための値を指します。
例えば、一時データの保存場所や、プログラムデータの場所などが環境変数で設定されており、多くのプログラムが参照しています。環境変数の表示方法について、以下のサンプルコードで確認しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「set」コマンドを実行する # すべての環境変数を表示する os.system("set") // 実行結果
環境変数にはさまざまな種類があるため、どの変数にどんな役割があるか分かりづらいこともあるでしょう。しかし、上手く動作しないプログラムやアプリがある場合は、参照されている環境変数を確認することで、どこに問題があるか把握しやすくなります。
「time」は、コンピューターの時刻を設定するためのコマンドです。以下のサンプルコードのように、os.system()関数にtimeコマンドを引き渡すことで、現在時刻を詳細に表示できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「time」コマンドを実行する # コンピューターの時刻を設定する os.system("time") // 実行結果
なお、timeコマンドで取得できる時間はパソコンで設定しているものであり、その設定が正しくない場合は誤った時間が表示されるので注意が必要です。また、「現在の時刻」の下に「新しい時刻を入力してください」と表示されていますが、管理者権限でコマンドプロンプトを開いた場合は新しい日付を設定できます。
しかし、Pythonからos.system()などの関数でコマンドを実行する際は、管理者権限を取得できないためこの機能は使えません。そこで、単に現在時刻を表示したい場合は、以下のサンプルコードのように「/Tオプション」を付けて「”time /t”」としましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「time」コマンドを実行する # コンピューターの時刻を設定する # 「/Tオプション」を付けると、単に現在の時刻だけが表示される os.system("time /t") // 実行結果
「date」は、現在の年月日を表示するためのコマンドです。先ほどのtimeコマンドが時間を表示するものであるのに対し、dateコマンドを使うと以下のように日付が表示されます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「date」コマンドを実行する # コンソール画面に現在の年月日が表示される os.system("date") // 実行結果
先ほどのtimeコマンドと同じように、dateコマンドでも「現在の日付」の下に、「新しい日付を入力してください」と表示されています。
しかし、管理者権限を取得することはできないので、以下のように「/Tオプション」を付けて「”date /t”」としましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「date」コマンドを実行する # コンソール画面に現在の年月日が表示される # 「/Tオプション」を付けると、単に現在の日付だけが表示される os.system("date /t") // 実行結果
先ほどのtimeコマンドと組み合わせると、以下のように現在の日付と時刻をセットで表示することができます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「date」コマンドを実行する # コンソール画面に現在の年月日が表示される # 「/Tオプション」を付けると、単に現在の日付だけが表示される os.system("date /t") # 「time」コマンドを実行する # コンピューターの時刻を設定する # 「/Tオプション」を付けると、単に現在の時刻だけが表示される os.system("time /t") // 実行結果
「notepad」は、「メモ帳」を表示するためのコマンドです。Windows PCに標準搭載されているアプリの多くは、実行ファイル(.exe)の正式名称を指定することで、以下のサンプルコードのようにos.system()で実行できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「notepad」コマンドを実行する # 「メモ帳」が自動的に開く os.system("notepad") // 実行結果
このように、単にファイル名を指定するだけで、標準アプリを起動できるので便利です。なお、メモ帳の正式名称は「notepad.exe」ですが、最後の「.exe」は省略しても構いません。以下のようなファイルは、基本的には同様の方法で実行することが可能です。
実行ファイル「.exe」の名称(コマンド) | プログラム名 |
---|---|
appwiz.cpl | プログラムと機能 |
calc | 電卓 |
charmap | 文字コード表 |
compmgmt.msc | コンピューターの管理 |
control | コントロールパネル |
control netconnections | ネットワーク接続 |
devmgmt.msc | デバイスマネージャー |
dxdiag | DirectX診断ツール |
eudcedit | 外字エディター |
eventvwr | イベントビューアー |
explorer | エクスプローラー |
firewall.cpl | WindowsDefenderファイアウォール |
inetcpl.cpl | インターネットのプロパティ |
magnify | 拡大鏡 |
main.cpl | マウスのプロパティ |
mmc | Microsoft管理コンソール |
msconfig | システム構成 |
msinfo32 | システム情報 |
mspaint | ペイント |
mstsc | リモートデスクトップ接続 |
netplwiz | ユーザーアカウント |
notepad | メモ帳 |
osk | スクリーンキーボード |
perfmon | パフォーマンスモニター |
powershell | Windows PowerShell |
powershell_ise | Windows PowerShell ISE |
regedit | レジストリエディター |
resmon | リソースモニター |
snippingtool | Snipping Tool |
services.msc | サービス |
sysdm.cpl | システムのプロパティ |
taskmgr | タスクマネージャー |
taskschd | タスクスケジューラ |
tpm.msc | コンピューターのトラステッドプラットフォームモジュール(TPM)の管理 |
wf.msc | セキュリティが強化されたWindows Defenderファイアウォール |
winver | Windowsのバージョン情報 |
write | ワードパッド |
「文字コード表(charmap)」のように、普段は滅多に使うことがないものの便利なアプリもあるので、この機会に試してみると良いでしょう。
ちなみに、os.start()関数やコマンドプロンプトで、これらのアプリをファイル名のみ指定して起動できるのは、実行ファイルが存在する「C:\Windows\System32」ディレクトリが、環境変数「PATH」に含まれているからです。実際に、先ほど紹介したsetコマンドで「PATH」の項目を見てみると、このディレクトリが設定されていることが分かります。
「start」は、その他のアプリケーションを起動するためのコマンドです。Windows OSに標準搭載されている「電卓」「ペイント」「タスクマネージャー」などのアプリは、前述したように実行ファイル名を指定すれば起動できます。
しかし、ユーザーが個別にインストールしたプログラムについては、実行ファイル名だけでは起動できません。
例えば、Webブラウザ「Google Chrome」は、「C:\Program Files\Google\Chrome\Application\chrome.exe」などの場所に格納されています。ところが、コマンドで「chrome.exe」と入力しても起動できません。
そこで必要になるのが「start」コマンドです。以下のサンプルコードのように、「start 実行ファイル名」の形式で指定すると、Google Chromeなどのアプリをコマンドプロンプトから起動できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「start」コマンドで「Google Chrome」を起動する os.system("start chrome") // 実行結果
そのほかにも、多くのプログラムをstartコマンドで起動できます。ただし、このstartコマンドは、「HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths」というレジストリキーの値を参照します。
つまり、アプリケーションのファイルパスがこのレジストリに含まれている場合のみ、「start ファイル名」の構文でアプリを起動できるということです。実際に、以下のサンプルコードでレジストリに登録されているアプリ名を確認してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「reg query」コマンドで「HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths」に登録されているアプリを表示する # finsdtr で「.exe」を含む要素だけを抽出し、「/I」で大文字と小文字を区別しないように設定している os.system("reg query \"HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\" | findstr /I \".exe\"") // 実行結果
入力するコマンド自体は「reg query “HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths” | findstr /I .exe」ですが、後述するエスケープシーケンスなどの理由から「”」の前に「/」を挿入している部分があります。上記の実行例はあくまで一例ですが、このように多数のアプリがレジストリに登録されており、「start ファイル名」のコマンドで実行可能です。
つまり、環境変数「PATH」やレジストリに登録されていないファイルは、startコマンドでファイル名を指定するだけでは起動できないということです。例えば、Cドライブの「Testフォルダ」にある「Test.txt」というファイルは、「os.system(“Test.txt”)」と指定しても起動できません。
そこで「絶対パス」によるファイルの指定が必要です。絶対パスとは、ファイル名やディレクトリ名だけではなく、ドライブ名から指定するファイルパスを指します。前述した例では、「C:\Test\Test.txt」となります。これを以下のサンプルコードのように、startコマンドで指定すると「Test.txt」を起動することが可能です。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「start」コマンドで「C:\Test\Test.txt」を起動する os.system("start C:\Test\Test.txt") // 実行結果
ただし、絶対ファイルパスに「スペース」が含まれる場合は、上記の方法では開けないので注意が必要になります。なぜなら、コマンドプロンプトでは、スペースはコマンドの区切り文字となっているからです。
そこでファイルパスを「クォーテーションマーク(”)」で囲み、一連の文字列として認識させてみましょう。なおソースコード上では、エスケープシーケンス「\」を使って、クォーテーションマークは「\”」と記載しないといけません。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「start」コマンドで「Google Chrome」を起動する os.system("start \"C:\Program Files\Google\Chrome\Application\chrome.exe\"") // 実行結果
ところが、コマンドプロンプトが起動するだけで、Google Chromeは開きません。クォーテーションマークで囲った部分は、ウィンドウタイトルとして認識されるのが原因です。
実際に、上記の実行結果を見てみると、タイトル部分にファイルパスが表示されてしまっています。そのため以下のサンプルコードのように、「start “タイトル” “ファイルパス”」として、3つ目の要素としてファイルパスを指定する必要があります。なお、ウィンドウタイトルは空白でも構いません。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「start」コマンドで「Google Chrome」を起動する os.system("start \"\" \"C:\Program Files\Google\Chrome\Application\chrome.exe\"") // 実行結果
ちなみに、startコマンドは以下のように、既定のWebブラウザで特定のWebサイトを表示させることも可能です。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「start」コマンドで既定のWebブラウザを起動し、「https://www.jma.go.jp/jma/index.html」にアクセスする os.system("start https://www.jma.go.jp/jma/index.html") // 実行結果
「tasklist」は、実行中のタスクやサービスをすべて表示するためのコマンドです。以下のサンプルコードのように、os.system()関数の引数に「”tasklist”」を指定することで、タスクやサービスの一覧が列挙されます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「tasklist」コマンドを実行する # 実行中のタスクやサービスがすべて表示される os.system("tasklist") // 実行結果
なお「PID」はプロセスIDを指し、後述する「taskkill」コマンドを使用し、任意のタスクを終了させるときなどに役立ちます。
「taskkill」は、指定したタスクやサービスを終了させるためのコマンドです。以下のサンプルコードのように、「taskkill /PID タスクID」と記載することで、タスクやサービスをただちに終了できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「taskkill」コマンドを実行する # 「taskkill /PID タスクID」と指定することで、タスクやサービスを終了できる os.system("taskkill /PID 18732") // 実行結果 「tasklist」コマンドで、当該タスク・サービスのPIDを確認する 「taskkill」コマンドで、当該タスク・サービスのPIDを指定する ただちに当該タスク・サービスの終了処理が行われる
ちなみに「/PID」のあとの「タスクID」は、前述したtasklistコマンドのPID項目で確認できます。
ただし、実行中のタスクやサービスには、コンピューターの制御に必要なものもあるため、不用意に削除するとシステムの動作が不安定になる恐れがあります。taskillコマンドでは、あくまで自身で起動したプログラムのみ終了するようにしましょう。
「dir」は、現在のディレクトリ構造を表示するためのコマンドです。Pythonからos.system()関数などでdirコマンドを実行すると、基本的にはモジュール(スクリプト)があるディレクトリが表示されます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「dir」コマンドを実行する # 現在のディレクトリ構造を表示する os.system("dir") // 実行結果
上記のように、ディレクトリは<DIR>と表示され、右側の「.」で階層構造を示します。ディレクトリ名やファイル名に加えて、それぞれの個数も表示されるので便利です。
「md」は、現在のディレクトリに新たなディレクトリを作成するためのコマンドです。先ほどの「dir」コマンドで表示された、つまり実行モジュールがあるディレクトリが対象となります。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「md」コマンドを実行する # 現在のディレクトリに新たなディレクトリを作成する os.system("md Test") // 実行結果 実行前 実行後
ちなみに、すでに存在するディレクトリ名を指定した場合は、以下のようなエラーが表示されます。
なお、カレントディレクトリ以外の場所にフォルダを作成したい場合は、新たなディレクトリ名を「絶対パス」で指定する必要があります。絶対パスとは、ファイル名やディレクトリ名だけではなく、ドライブ名から指定するファイルパスを指します。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「md」コマンドを実行する # 新たなディレクトリ名を「絶対パス」で指定すると、カレントディレクトリ以外の場所にもディレクトリを作成できる os.system("md C:\Test") // 実行結果
上記のサンプルプログラムは、Cドライブ直下に「Test」というディレクトリを作成するものです。絶対パスは「C:\Test」となるため、これをmdコマンドで指定する必要があります。
「move」は、ファイルやディレクトリを別の場所に移動するためのコマンドです。以下のサンプルコードのように、「move 移動前のパス 移動後のパス」という構文で使用しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「move」コマンドを実行する # ファイルやディレクトリを別の場所に移動する os.system("move Test.txt Test\Test.txt") // 実行結果 コンソール画面 実行前 実行後
なお、moveコマンドを使用すると、以下のようにファイル名やディレクトリ名を変更することもできます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「move」コマンドを実行する # ファイル名やディレクトリ名を変更することもできる os.system("move Test.txt Changed.txt") // 実行結果 コンソール画面 実行前 実行後
ただし、ファイルやディレクトリの名前を変更するために、「rename」という専用コマンドがあるため、そちらを利用するほうがいいでしょう。
「xcopy」は、ファイルやディレクトリをコピーするためのコマンドです。「xcopy コピー元 コピー先」という構文で使用します。ディレクトリ名を指定すると、内部のファイルもまとめてコピーできるので便利です。ただし、すべてをコピーするためにはオプションの指定が必要です。
まずは適当な場所に「Testフォルダ」を作成し、内部に「Sourceフォルダ」を作成してください。Sourceフォルダの内部にも、ファイルやフォルダを作成することがポイントです。そのうえで、以下のサンプルコードを実行してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「xcopy」コマンドを実行する # 「xcopy コピー元 コピー先」と記載することで、ファイルやディレクトリをコピーできる os.system("xcopy F:\Test\Source F:\Test\Destination") // 実行結果 コンソール画面 「Destination」フォルダ
実行時に確認画面が表示されるので、コピー先がファイルの場合は「F」、ディレクトリの場合は「D」を指定します。上記の実行結果を見ると、指定したディレクトリより深い階層のディレクトリが、正しくコピーされていないことが分かります。デフォルトの挙動では、指定したディレクトリに存在するファイルとディレクトリのみ、コピーされるからです。
深い階層のディレクトリもまとめてコピーするためには、「/e」と「/h」のオプションを指定して、「xcopy /e /h コピー元 コピー先」という構文で記載する必要があります。「/e」はファイルが存在しない場合もディレクトリごとコピーし、「/h」は隠しファイルやシステムファイルもすべてコピーします。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「xcopy」コマンドを実行する # 「xcopy /e /h コピー元 コピー先」と記載することで、深い階層にあるファイルやディレクトリも # 「/e」:ファイルが存在しない場合もディレクトリごとコピーする # 「/h」:隠しファイルやシステムファイルもすべてコピーする os.system("xcopy /e /h F:\Test\Source F:\Test\Destination") // 実行結果 コンソール画面 「Destination\Inner\Deep」フォルダ
先ほどは3個のファイルしかコピーできませんでしたが、「/e」と「/h」のオプションを指定することで、9個すべてのファイルをコピーすることができました。そのためxcopyコマンドを使用するときは、基本的には「xcopy /e /h」とセットで覚えておくといいでしょう。
「rename」は、ファイルやディレクトリの名前を変更するためのコマンドです。「以下のサンプルコードのように、「rename 古い名称 新しい名称」という構文で使用しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「rename」コマンドを実行する # ファイルやディレクトリの名前を変更する os.system("rename Old.txt New.txt") // 実行結果 実行前 実行後
ファイル名はもちろんディレクトリの名前も変更できるので、必要に応じて活用してみましょう。
「del」は、指定したファイルを削除するためのコマンドです。以下のサンプルコードのように、削除したいファイルのパスを引き渡すことで削除できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「del」コマンドを実行する # ファイルを削除する os.system("del Test.txt") // 実行結果 実行前 実行後
なお絶対パスを指定すると、カレントディレクトリ以外の場所にあるファイルも削除できます。ただし、delコマンドはディレクトリ(フォルダ)の削除はできないので、ファイルを削除したいときだけ使うようにしましょう。
「rd」は、指定したディレクトリを削除するためのコマンドになります。先ほどのdelコマンドと同様に、パスを指定するだけで使えます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「rd」コマンドを実行する # ディレクトリを削除する os.system("rd Test") // 実行結果 実行前 実行後
上記のように、指定したディレクトリを簡単に削除できます。ただし、ディレクトリの内部にファイルがある場合は、以下のようなエラーが表示されます。
ディレクトリ内部のファイルやサブディレクトリもまとめて削除するためには、「/sオプション」を指定する必要があります。任意の場所にディレクトリを作成し、内部にファイルやサブディレクトリを追加したうえで、以下のサンプルコードを実行してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「rd」コマンドを実行する # 内部のファイルやサブディレクトリも含めて、ディレクトリを削除する # ファイルパスについては必要に応じて書き換えてください os.system("rd /s F:\Test\Test") // 実行結果 コンソール画面 実行前 実行後
上記のように、/sオプションを指定することで、サブディレクトリもまとめて削除できました。ただし、rdコマンドはファイル単体を削除することはできないので、その場合は前述したdelコマンドを使用しましょう。
「comp」は、指定した2つのファイルを比較するためのコマンドです。「comp ファイルA ファイルB」という構文で使用すると、以下のように2つのファイルに違いがあるか・ないかを判定できます。適当なテキストファイルを2つ用意して、両者の内容が同じ・異なるパターンで試してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「comp」コマンドを実行する # 2つのファイルの違いを比較する os.system("comp A.txt B.txt") // 実行結果 2つのファイルの中身が同じ場合 2つのファイルの中身が異なる場合
なお現在のところ、compコマンドでは両者のファイルのどの部分が異なるか、詳細な比較はできないようです。compコマンドはファイル比較の機能としては不便なので、ファイル比較ツール(差分ツール)などを使用するほうがいいでしょう。
「title」は、コンソール画面のタイトルを変更するためのコマンドです。以下のサンプルコードのように、コマンドプロンプトの上部バーに表示されるタイトルを変更できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「title」コマンドを実行する # コンソール画面のタイトルを変更する os.system("title テスト用のコンソール画面") // 実行結果
何らかの理由で、ウィンドウのタイトルをオリジナルのものにしたい場合は、titleコマンドを活用してみましょう。
「color」は、コンソール画面の背景色と文字色を変更するためのコマンドです。「color 背景色・文字色」という構文で使用しますが、色は以下のいずれかの値から選択します。
値 | 色 |
---|---|
0 | 通常の黒色 |
1 | 通常の青色 |
2 | 通常の緑色 |
3 | 通常の水色 |
4 | 通常の赤色 |
5 | 通常の紫色 |
6 | 通常の黄色 |
7 | 通常の白色 |
8 | 通常の灰色 |
9 | 明るい青色 |
A | 明るい緑色 |
B | 明るい水色 |
C | 明るい赤色 |
D | 明るい紫色 |
E | 明るい黄色 |
F | 明るい白色 |
背景色と文字色は、いずれも上記の値から選びます。例えば、背景色を「通常の白色」・文字色を「通常の青色」にする場合は、「color 71」と記載します。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「color」コマンドを実行する # コンソール画面の「背景色」と「文字色」を変更する # colorのあとに背景色と文字色を以下の値から2桁で指定する # 0:通常の黒色 # 1:通常の青色 # 2:通常の緑色 # 3:通常の水色 # 4:通常の赤色 # 5:通常の紫色 # 6:通常の黄色 # 7:通常の白色 # 8:通常の灰色 # 9:明るい青色 # A:明るい緑色 # B:明るい水色 # C:明るい赤色 # D:明るい紫色 # E:明るい黄色 # F:明るい白色 os.system("color 71") # 背景色は「通常の白色(7)」・文字色は「通常の青色(1)」にする // 実行結果
CUIプログラミングで意識することは少ないかもしれませんが、このcolorコマンドを活用することで表示画面をデザインできます。ただし、背景色と文字色を同じ色にするとメッセージが読めなくなるため、カラーの変更は行われません。
「timeout」は、指定した時間だけ処理を待機するためのコマンドです。以下のサンプルコードのように、「timeout /t 待機時間」という構文で記載すると、Pythonのtime.sleep()関数のようにプロセスが一時停止します。なお「-1」を指定すると、キー入力が行われるまで無限に待機します。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「timeout」コマンドを実行する # 「timeout 時間」と記載すると、指定した時間だけ処理を待機する # ユーザーがキー入力を行うと、時間内であっても待機状態は解除される os.system("timeout /t 10") // 実行結果
オプションを指定しない場合は、ユーザーが何らかのキーを入力した時点で、待機状態が解除されます。通常のキー入力を無視したい場合は、以下のように「/nobreak」オプションを指定して、「timeout /t 待機時間 /nobreak」という構文で記載しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「timeout」コマンドを実行する # 「timeout 時間」と記載すると、指定した時間だけ処理を待機する # 「/nobreak」オプションを指定すると、指定した時間が経過するまで待機状態は解除されない # ただし、ユーザーが「CTRL + C」を入力した場合のみ、待機状態を解除できる os.system("timeout /t 10 /nobreak") // 実行結果 待機開始時 「CTRL + C」入力時
上記の実行結果のように、ユーザーが「CTRL + C」を入力すると、「KeyboardInterrupt」例外が発生するためエラーメッセージが表示されます。このメッセージを表示させたくない場合は、以下サンプルコードのようにKeyboardInterrupt例外を捕捉しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os try: # 「timeout」コマンドを実行する # 「timeout 時間」と記載すると、指定した時間だけ処理を待機する # 「/nobreak」オプションを指定すると、指定した時間が経過するまで待機状態は解除されない # ただし、ユーザーが「CTRL + C」を入力した場合のみ、待機状態を解除できる os.system("timeout /t 10 /nobreak") except KeyboardInterrupt: # ユーザーが「CTRL + C」を入力すると「KeyboardInterrupt」例外が発生するので、終了メッセージを表示する print("待機状態を解除しました") // 実行結果 待機開始時 「CTRL + C」入力時
また、コマンドの終端に「> nul」を付加することで、コマンドプロンプトにメッセージを表示しないようにできます。「>」はリダイレクト記号で、メッセージの出力先を任意のファイルに変更するためのものです。
「nul」は空ファイルを示すため、コマンドプロンプトには何も表示されなくなります。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「timeout」コマンドを実行する # 「timeout 時間」と記載すると、指定した時間だけ処理を待機する # 「/nobreak」オプションを指定すると、指定した時間が経過するまで待機状態は解除されない # ただし、ユーザーが「CTRL + C」を入力した場合のみ、待機状態を解除できる # 「> nul」オプションを追加すると、待機メッセージが表示されなくなる os.system("timeout /t 10 /nobreak > nul") // 実行結果
ちなみに、timeout以外のコマンドに「> nul」を付加した場合も、同じような結果が得られます。
「py」は、外部のPythonスクリプトを実行するためのコマンドです。以下のソースコードを「Test.py」という名称で、メインモジュールと同じディレクトリに保存し、サンプルコードを実行してみましょう。
// Test.py # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 適切なメッセージを表示する print("外部のPythonスクリプトが実行されました") // サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「py」コマンドを実行する # 「py ファイル名」の形式でPythonスクリプトを実行できる os.system("py Test.py") // 実行結果
pyコマンドで間接的に「Test.py」を実行しているため、その処理結果がコマンドプロンプトに表示されます。pyコマンドは、Pythonスクリプトをコマンドプロンプトから実行する際に多用するため、ぜひ覚えておきましょう。
「cls」は、コンソール画面の表示内容をすべて消去するためのコマンドです。以下のサンプルコードのようにclsコマンドを使用すると、すでに表示されているすべてのメッセージを削除できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「tasklist」コマンドを実行する # 実行中のタスクやサービスがすべて表示される os.system("tasklist") # 「cls」コマンドを実行する # コンソール画面を消去する # 先ほど「tasklist」で表示した画面がリセットされる os.system("cls") // 実行結果
上記のサンプルプログラムでは、tasklistコマンドを呼び出しているため、現在稼働中のプロセスやサービスが列挙されているはずです。しかし、直後にclsコマンドを使用したことから、そのメッセージが削除されています。コマンドプロンプトで処理を繰り返すときなどに、画面表示を分かりやすくするためにclsコマンドが便利です。
「exit」は、コマンドプロンプトを終了するためのコマンドです。以下のサンプルコードのように、exitコマンドを呼び出した時点で一連の処理を完了できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「exit」コマンドを実行する # コマンドプロンプトを終了する os.system("exit") // 実行結果
なお、後述するPythonの「インタラクティブモード(対話モード)」を終了するときは、exitではなく「exit()」と入力する必要があります。
「shutdown」は、コンピューターをシャットダウンするためのコマンドです。単にshutdownコマンドのみ入力すると、以下のようにヘルプが表示されます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「shutdown」コマンドを実行する # 「shutdown 操作 コマンド」の形式で処理を指定する # 操作とコマンドを指定しない場合は、ヘルプドキュメントが表示される os.system("shutdown") // 実行結果
「/s」がシャットダウン処理、「/t」でシャットダウンまでの時間を指定できます。以下のサンプルコードのように、「shutdown /s /t 秒数」というコマンドで、コンピューターを自動的にシャットダウンさせることが可能です。ただし、作業中のデータを必ず保存してから、このサンプルコードを実行するようにしてください。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「shutdown」コマンドを実行する # 「shutdown 操作 コマンド」の形式で処理を指定する # 「shutdown /s /t 60」とすると、60秒後にシャットダウンが行われる os.system("shutdown /s /t 60") // 実行結果
上記の実行結果のように、シャットダウンが行われることを示すメッセージが、画面上に表示されます。このシャットダウンを無効化したいときは、以下のサンプルコードのように「/a」オプションを指定しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「os」ライブラリをインポートする import os # 「shutdown」コマンドを実行する # 「shutdown 操作 コマンド」の形式で処理を指定する # 「shutdown /a」とすると、先ほどのシャットダウンを取り消すことができる os.system("shutdown /a") // 実行結果
このように、「/a」オプションを指定するとシャットダウンをキャンセルできます。ただし、「/s」オプションでシャットダウン時間を設定していない状態で「/a」オプションを使用すると、以下のようなエラーメッセージが表示されます。
os.system()で使用できる代表的なコマンドを解説しました。ただし現在では、機能性やセキュリティ強度などの観点から、os.system()より「subprocess」を使用することが推奨されています。
本章では、os.system()の代替手段として重要な、subprocessライブラリの使い方について、以下5つのポイントから解説します。
os.system()関数ではなくsubprocessライブラリを使用する場合、コマンドの入力はsubprocess.run()関数で行います。基本的な使い方はos.system()と同じで、subprocessライブラリをインポートしたあとに、以下の構文でsubprocess.run()を呼び出しましょう。
subprocess.run("コマンド")
ただしWindows PCの場合は、前述したような組み込みコマンドを使用すると、「指定されたファイルが見つかりません」と表示されます。そのため、引数に「shell = True」を追加する必要があります。subprocess.run()関数の使い方について、以下のサンプルコードで確認しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「dir」コマンドを実行する # 現在のディレクトリ構造を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される subprocess.run("dir", shell = True) // 実行結果
上記の実行結果は、dirコマンドを使用したコンソール画面です。使用できるコマンドや機能はos.system()と変わらないため、基本的には同じように使うことができます。つまり、subprocess.run()はos.system()のアップグレード版・上位互換だといえるでしょう。
なお、subprocess.call()でもsubprocess.run()と同じように、os.system()のコマンドを使用できます。subprocess.call()の使い方は、以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「time」コマンドを実行する # 現在の日時をコンソール画面上に表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される subprocess.call("time", shell = True) // 実行結果
このように、os.system()と同じ感覚で使える関数ですが、現在ではsubprocess.run()が推奨されているため、subprocess.call()は使用しないほうが無難です。
Pythonのsubprocess.run()関数では、戻り値としてさまざまな情報を取得できます。以下のように、subprocess.run()関数を実行すると「subprocess.CompletedProcess」オブジェクトを取得できます。
subprocess.CompletedProcessオブジェクト = subprocess.run("コマンド", shell = True)
subprocess.CompletedProcessオブジェクトでは、実行したコードに関する以下のような情報を取得できます。なお、下記の内容は2023年5月現在の「Python 3.11」のものであるため、新しいバージョンで機能が拡張されている可能性があります。また、サンプルコードを実行できない場合は、後述の「代替引数が使えない場合はPythonのアップデートが必要」項目をご確認ください。
args | 実行したコマンド 文字列もしくはリスト型 |
returncode | コマンドの終了コード 正常終了は「0」で、異常終了は「0以外」 |
stdout | ウィンドウに表示されたメッセージ内容 バイトコードもしくは文字列 |
stderr | エラーメッセージ バイトコードもしくは文字列 |
これらの情報は、subprocess.run()でコマンドがどのように実行されたか、またその実行結果を把握するために役立ちます。実際に、subprocess.run()の戻り値を表示してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「ver」コマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される result = subprocess.run("ver", shell = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
CompletedProcessオブジェクト情報が表示されましたが、「args」と「returncode」が表示されていません。これは、subprocess.run()の引数で表示設定をしていないことが理由です。そこで、subprocess.run()の引数に「capture_output = True」を追加することで、以下のサンプルコードのように出力メッセージを取得できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「ver」コマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「capture_output = True」とすると、コンソール画面での出力内容を戻り値として取得できる result = subprocess.run("ver", shell = True, capture_output = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
「stdout」には出力されたメッセージ内容、「stderr」にはエラーメッセージが格納されます。しかし、メッセージに「b」や「\r\n」など余分な文字が表示されています。この場合、出力型がバイトコードになっていることが理由なので、subprocess.run()の引数に「text = True」を追加しましょう。そうすると出力メッセージを文字列として取得できます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「ver」コマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「capture_output = True」とすると、コンソール画面での出力内容を戻り値として取得できる # 「text = True」とすると、各種メッセージを文字列形式で取得できる result = subprocess.run("ver", shell = True, capture_output = True, text = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
なお、文字コードを指定したい場合は、「text = True」の代わりに「encoding = “utf-8″」と記載することでも、同じ結果が得られます。ちなみに、不正なコマンドを入力するなどでエラーが出た場合は、以下のような画面が表示されます。
「returncode」の値が「1」になっていることがポイントです。このように、入力したコマンドが正常に実行されなかった場合、終了コードは「0以外」になります。
Pythonのsubprocess.run()関数やsubprocess.CompletedProcessオブジェクトは、「Python 3.5」になってから追加された機能です。さらに、subprocess.run()のcapture_output・textといった引数は、Python 3.7以降の新機能です。このように、Pythonのsubprocess関連のオブジェクト・関数は機能拡張が続いています。
以上の点から、コンピューターにインストールされているPythonのバージョンが古いと、前述したサンプルコードを実行できません。Python 3.5以降でcapture_outputやtextが使えない場合は、以下サンプルコードのように代替引数を使用しましょう。subprocess.run()関数で、「stdout = subprocess.PIPE」「stderr = subprocess.PIPE」「universal_newlines = True」の3つの引数を指定することで、出力メッセージを取得できます。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「ver」コマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「stdout = subprocess.PIPE」「stderr = subprocess.PIPE」で「capture_output = True」の代用になる # 「universal_newlines = True」で「text = True」の代用になる result = subprocess.run("ver", shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
ただし、Pythonのバージョンが3.5以前の場合は、そもそもsubprocess.run()関数やsubprocess.CompletedProcessオブジェクト自体が存在しません。前述したように、subprocess.call()関数はすでに非推奨なので、今後は削除される可能性があります。そのため、この機会にPythonのバージョンをアップデートしておくことをおすすめします。
「stdout」「stderr」「universal_newlines」などの代替引数が使えない場合や、subprocess.run()関数やsubprocess.CompletedProcessオブジェクトがない場合は、今後のためにPythonをアップデートしておくことをおすすめします。Pythonのアップデートは、公式サイトから簡単な手順で行えます。
公式サイトにアクセスしたら、画面上部の黄色い「Download Python バージョン名」というボタンをクリックしてください。インストーラーを実行すると、以下のような画面が表示されるので、画面下部の「Add python.exe to PATH」を必ずチェックし、「Install Now」を選択しましょう。
インストールが正しく完了したか確認するために、コマンドプロンプトを管理者権限で起動し、「python」と入力してください。以下のようにPythonのバージョン情報が表示されるので、先ほどインストールしたバージョンと一致すればOKです。
上記のようなメッセージが表示されない場合は、「アプリ実行エイリアス」の設定が原因です。Windowsの設定画面から「アプリと機能」へ進み、画面中央付近の「アプリ実行エイリアス」を選択してください。
そのうえで、Python関連の2つの「アプリ インストーラー」をオフにしてから、先ほどのコマンドを改めて実行するとPythonのバージョン情報が表示されます。
さらに、IDEで使用するPythonのバージョンも変更する必要があります。Visual Studioの場合は、ソリューションエクスプローラーでプロジェクトを右クリックして「プロパティ」へ進み、「全般」の「インタープリター」をPython最新バージョンに変更すればOKです。
以上の設定が完了したら、先ほどのサンプルコードを再度実行してみてください。最新バージョンのPythonを利用できるため、正しい結果が得られるはずです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「ver」コマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「capture_output = True」とすると、コンソール画面での出力内容を戻り値として取得できる # 「text = True」とすると、各種メッセージを文字列形式で取得できる result = subprocess.run("ver", shell = True, capture_output = True, text = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
subprocessライブラリの基本的な使い方を踏まえて、活用法・テクニックについても見ていきましょう。以下の7つのポイントは、subprocessライブラリを使いこなすために重要です。
subprocess.run()関数の引数に「check = True」を追加すると、コマンド実行でエラーが発生したときに「例外」を出すことができます。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 存在しないコマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「capture_output = True」とすると、コンソール画面での出力内容を戻り値として取得できる # 「text = True」とすると、各種メッセージを文字列形式で取得できる # 「check = True」とすると、終了コードが0以外のときに例外を発生できる result = subprocess.run("test", shell = True, capture_output = True, text = True, check = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
上記のサンプルプログラムでは、存在しない「test」というコマンドを実行しようとしたので、「subprocess.CalledProcessError」例外が発生しました。0以外の戻り値である「1」が返ったこともメッセージで記載されています。
メッセージをコンソール画面ではなくファイルに出力したいときは、subprocess.run()の引数に「stdout = fp」を追加しましょう。fpはファイルオブジェクトで、以下のサンプルコードのように、with文で作成すると便利です。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess with open("Command.txt", "w") as fp: # 「shutdown」コマンドを実行する # 「shutdown 操作 コマンド」の形式で処理を指定する # 操作とコマンドを指定しない場合は、ヘルプドキュメントが表示される # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「stdout = fp」とすることで、指定したファイルにメッセージを出力できる # ただしstdoutを指定する場合は、「capture_output」と「text」は利用できない # 「check = True」とすると、終了コードが0以外のときに例外を発生できる result = subprocess.run("shutdown", shell = True, stdout = fp, check = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報をコンソール画面に表示する print(result) // 実行結果 コンソール画面 Command.txt
「stdout = fp」でメッセージの出力先を指定するため、プログラマ側でファイルへの書き出し処理を行う必要はありません。ただし、stdout引数を使用する場合は、「capture_output」と「text」は利用できません。なお、「check = True」で例外を発生できる点は、stdout引数を使用しない場合と同じです。
subprocess.run()は、文字列を標準入力に引き渡すこともできます。標準入力とは、Pythonのコンソール画面でユーザーの入力を受け取るための機能で、以下のサンプルコードのようにinput()関数で使用します。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 標準入力から整数値numを受け取る num = int(input("整数値を入力してください:")) # 0からnumまでの合計値を表示する print(f"0から{num}までの合計値:{num * (num + 1) // 2}") // 実行結果
上記のサンプルプログラムは、ユーザーが入力した整数値numを受け取り、0からnumまでの合計値を表示するものです。重要なポイントは、「input(“整数値を入力してください:”)」の部分で、標準入力からユーザーの入力値を文字列で取得していることです。以下の構文で「input引数」を追加することで、subprocess.run()で標準入力に文字列を引き渡せます。
subprocess.run("py モジュール名.py", shell = True, input = "標準入力に引き渡す文字列", capture_output = True, text = True, check = True)
「text = True」にしないと、文字列ではなくバイトコードを標準入力に引き渡すことになり、エラーが出てしまいます。subprocess.run()のこのサンプルコードを「Process.py」という名称で、メインモジュールと同じディレクトリに保存したうえで、以下のサンプルコードを実行してみましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 存在しないコマンドを実行する # Windowsのバージョン情報を表示する # なお、組み込みコマンドを利用する場合は、「shell引数」をTrueにする必要がある # shellを有効化することによって、デフォルトの環境変数が参照される # 「capture_output = True」とすると、コンソール画面での出力内容を戻り値として取得できる # 「text = True」とすると、各種メッセージを文字列形式で取得できる # 「check = True」とすると、終了コードが0以外のときに例外を発生できる result = subprocess.run("py process.py", shell = True, input = "100", capture_output = True, text = True, check = True) # 戻り値「subprocess.CompletedProcessオブジェクト」の情報を表示する print (result) // 実行結果
このように、subprocess.run()のinput引数で、標準入力に「10」という文字列を引き渡すことができました。input引数の文字列の形式と、受け取り側が要求する形式が一致していれば動作するため、何らかの処理において外部スクリプトを自動的に実行するときなどに役立つでしょう。
subprocess.run()関数に「timeout = 秒数」を追加することで、指定した時間が経過したあとにタイムアウトを発生させることができます。詳細を以下のサンプルコードで確認しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「timeout引数」を使用する場合はtry-catch文で囲む try: # 「timeout」コマンドを実行する # 「timeout 時間」と記載すると、指定した時間だけ処理を待機する # ユーザーが「CTRL + C」を入力すると、待機状態を解除できる # 「timeout = 秒数」で指定した時間の経過後に、タイムアウトが発生する result = subprocess.run("timeout /nobreak 10", shell = True, timeout = 3, check = True) # コマンドの実行結果を表示する print(result) # タイムアウトが発生した場合は「subprocess.TimeoutExpired」例外が投げられる except subprocess.TimeoutExpired as e: # タイムアウトが発生すると、実行したコマンドは強制的に終了する # 例外メッセージの内容を表示する print(e) // 実行結果 タイムアウト前 タイムアウト後
上記のサンプルプログラムは、「timeout /nobreak 10」でコマンドプロンプトを待機状態にさせたうえで、timeout引数で3秒後にタイムアウトさせています。3秒後に待機状態が解除され、「subprocess.TimeoutExpired」例外が発生します。
これまでのサンプルコードでは、subprocess.run()関数でコマンド処理を行っていました。subprocess.run()は「同期処理」の関数なので、処理が完了するまで待機するという性質があります。しかし、コマンドの実行中にほかの処理を行いたいこともあるでしょう。
そこで、subprocess.Popen()関数を使用すると、待機しない「非同期処理」を行うことができます。subprocess.Popen()は内部でsubprocess.run()を呼び出しているため、基本的な構文や引数はsubprocess.run()と同じです。subprocess.Popen()で非同期処理を行う方法について、以下のサンプルコードで確認しましょう。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「time」ライブラリをインポートする import time # subprocess.Popen()関数で「timeout」コマンドを実行する # subprocess.run()と異なり、subprocess.Popen()は処理の終了を待たない # その代わりに「Popenオブジェクト」が戻り値となり、Popen.poll()で処理状況を確認できる result = subprocess.Popen("timeout /nobreak 3", shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE, text = True) # 非同期処理の効果を確認するために、適当な変数を用意する num = 0 # Popen.poll()の戻り値が「None」であれば実行中、「not None」であれば終了している while result.poll() is None: # プロセスの進行状況を表示する print(f"プロセスID「{result.pid}」の処理を待機中です") # ほかの処理を行う(今回は一例として適当な変数に1を足す) num += 1 # ほかの処理を行っているメッセージを表示する print(f"非同期処理を行っています:{num}") # 0.5秒だけ待機する time.sleep(0.5) # 戻り値の中身を表示する print(result) # 非同期で処理した変数の値を表示する print(f"非同期で処理した変数の値:{num}") // 実行結果 非同期処理の実行中 非同期処理の完了時
subprocess.Popen()の戻り値は、コマンド処理のステータスを示します。このオブジェクトのpoll()が「None」を返す間は処理が続いており、「not None」であれば処理は完了しています。subprocess.Popen()を呼び出したあと、無限ループでresult.poll()の値をチェックして、内部で非同期処理を行っていることがポイントです。今回は簡易的な処理を行いましたが、複雑な処理を行う場合はプログラムの高速化に役立つでしょう。
subprocess.Popen()でコマンドを実行したあとに、その処理を途中で強制終了する場合は、戻り値の「terminate()」関数を呼び出します。poll()の結果が「not None」であれば、プロセスの強制終了が完了しています。詳細は以下のサンプルコードのとおりです。
// サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「time」ライブラリをインポートする import time # subprocess.Popen()関数で「timeout」コマンドを実行する # subprocess.run()と異なり、subprocess.Popen()は処理の終了を待たない # その代わりに「Popenオブジェクト」が戻り値となり、Popen.poll()で処理状況を確認できる result = subprocess.Popen("timeout /nobreak 3", shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE, text = True) # プロセスを強制的に終了する # terminate()の代わりにkill()でもOK result.terminate() # Popen.poll()の戻り値が「None」であれば停止中、「not None」であれば完了している while result.poll() is None: # プロセスの停止状況を表示する print(f"プロセスID「{result.pid}」の処理を終了しています") # 戻り値の中身を表示する print(result) // 実行結果
whileループでpoll()関数の戻り値をチェックし、処理が完了しているか判断する点は、先ほどのサンプルコードと同じです。なお、処理の完了には多少の時間がかかるため、強制終了までにループが繰り返される回数は一定ではありません。
Pythonには、通常どおりスクリプトファイルを作成する以外にも、「インタラクティブモード(対話モード)」でプログラムを実行する方法があります。インタラクティブモードでは、コマンドプロンプト上でソースコードを直接入力しながら、その都度プログラムの実行結果を確認することが可能です。
Pythonのインタラクティブモードは、上記の画面のように「python -i」のコマンドで起動できます。それからPythonのソースコードを入力していくと、画面上に実行結果が表示されます。ソースコードが表示される以外は、IDEから実行する場合と基本的な部分は同じです。
ソースコードに誤りがある場合は、以下のようにエラーメッセージが表示されます。前述したように、インタラクティブモードを終了する場合は「exit()」関数を呼び出しましょう。
Pythonのインタラクティブモードをsubprocess.Popen()関数から使用すると、コマンドプロンプトへのソースコード入力をプログラムで自動化できます。メインモジュールと同じ場所に、以下のソースコードを「Shell.txt」という名称で保存し、サンプルコードを実行してみましょう。
// Shell.txt # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「random」ライブラリをインポートする import random # ランダムな数値の計算を行う a = random.randint(0, 100) * 100 b = random.randint(0, 100) * 100 c = a * b # 計算結果を表示する print(f"{a} * {b} = {c}") // サンプルプログラム # 文字コードを「UTF-8」に設定する # エラーが出る場合は「Shift-JIS」に変更してください # coding: UTF-8 # 「subprocess」ライブラリをインポートする import subprocess # 「time」ライブラリをインポートする import time # 「threading」ライブラリをインポートする import threading # Shellクラス|Pythonのインタラクティブモードを操作する class Shell: # コンストラクタ def __init__(self): # コマンドを保存するための変数を用意する self.commands = "" # 「python -i」コマンドを実行し、Pythonのインタラクティブモードを起動する # 標準入力への入出力は文字列形式で行い、各種メッセージを捕捉する self.process = subprocess.Popen("python -i", shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, text = True) # メッセージ処理をリアルタイムで行うためにスレッドを起動する thread = threading.Thread(target = self.message) # 別スレッドでself.message()関数の処理を行う thread.start() # 最初のメッセージを表示するために、メインスレッドを1秒間待機させる time.sleep(1) # command()関数|入力されたコマンドを保存する def command(self, command): # メンバ変数にコマンドを記録する self.commands += command + "\n" # execute()関数|入力されたコマンドを実行する def execute(self): # stdin.write()関数を呼び出すと、標準入力にコマンドを実際に転送できる self.process.stdin.write(self.commands + "\n") # 入力されたコマンドを表示する # 前回のコマンドと区別するために、最初に改行を挿入する print("\n" + self.commands) # 新たなコマンドを入力できるように、メンバ変数をクリアする self.commands = "" # stdin.flush()を呼び出すことで、入力したコマンドを実行できる self.process.stdin.flush() # 処理前に新たなコマンドが表示されないように、メインスレッドを1秒間待機させる time.sleep(1) # 標準入力の別スレッドでstdoutをqueueに格納するための関数 def message(self): # 標準出力にメッセージが追加されるたびに表示する # リアルタイムで処理できるように別スレッドで実行する for line in self.process.stdout: print(line, end = "") # スレッドの終了メッセージを表示する print("スレッドを終了します") # main()|プログラムのエントリーポイント if __name__ == "__main__": # Shellオブジェクトのインスタンスを生成する shell = Shell() # Pythonのインタラクティブモード起動中は、無限ループで処理を繰り返す while shell.process.poll() is None: # あらかじめファイルに記載しているPythonスクリプトを、インタラクティブモードで実行する # なお、Pythonスクリプトを読み込む場合は、「encoding = "UTF-8"」を設定する必要がある with open("Shell.txt", encoding = "UTF-8") as f: shell.command(f.read()) # スクリプトを実行する shell.execute() # コマンドを入力して実行する shell.command("print(\"Hello, World!\")") shell.execute() # 「exit()」と入力することで、Pythonのインタラクティブモードを終了できる shell.command("exit()") shell.execute() # インタラクティブモードの終了メッセージを表示する print("Pythonのインタラクティブモードを終了します") // 実行結果
Pythonからインタラクティブモードを使用するのは、高度なテクニックなのでプログラムは複雑なものになります。「Shellクラス」では、コンストラクタでPythonのインタラクティブモードを起動し、別スレッドを生成しています。別スレッドでは、出力されたメッセージをリアルタイムで表示するために、「message()」を実行しています。
特に重要な部分は、「command()」と「execute()」の2つの関数です。command()には、実行したいコマンドを引き渡し、内部ではメンバ変数にコマンドを蓄積しています。ただし、command()を呼び出した時点では、コマンドは実行されません。蓄積したコマンドの実行は、execute()で行います。コマンドの実行は、subprocess.Popen()の戻り値からstdin.write()を呼び出し、コマンドを引き渡します。そのうえで、stdin.flush()を実行するとコマンドを実行することが可能です。
main()関数では、「Shell.txt」のスクリプトを実行したうえで、command()とexecute()で個別にコマンドを実行しています。コマンドを直接記載する場合は、クォーテーションマークの前にエスケープシーケンス「\」を入れる必要があります。以上のサンプルコードを応用することで、インタラクティブモードをプログラムから操作することが可能です。
Pythonのos.system()関数と、そのアップグレード版であるsubprocessライブラリの各種関数について、詳細を解説しました。コマンドプロンプトでは、さまざまなコマンドを実行できますが、Pythonでプログラムから操作することで効率化・自動化に役立ちます。今回ご紹介したサンプルコードを参考にして、さまざまなコマンドを実行してみましょう。
2024.06.17
子供におすすめのプログラミングスクール10選!学習メリットや教室選びのコツも紹介
#プログラミングスクール
2022.01.06
【完全版】大学生におすすめのプログラミングスクール13選!選ぶコツも詳しく解説
#プログラミングスクール
2024.01.26
【未経験でも転職可】30代におすすめプログラミングスクール8選!
#プログラミングスクール
2024.01.26
初心者必見!独学のJava学習方法とおすすめ本、アプリを詳しく解説
#JAVA
2024.01.26
忙しい社会人におすすめプログラミングスクール15選!失敗しない選び方も詳しく解説
#プログラミングスクール
2022.01.06
【無料あり】大阪のおすすめプログラミングスクール14選!スクール選びのコツも紹介
#プログラミングスクール
2024.01.26
【目的別】東京のおすすめプログラミングスクール20選!スクール選びのコツも徹底解説
#プログラミングスクール
2024.01.26
【無料あり】福岡のおすすめプログラミングスクール13選!選び方も詳しく解説
#プログラミングスクール
2024.01.26
【徹底比較】名古屋のおすすめプログラミングスクール13選!選び方も詳しく解説
#プログラミングスクール
2024.01.26
【徹底比較】おすすめのプログラミングスクール18選!失敗しない選び方も徹底解説
#プログラミングスクール