Python でプログラムの優先度を変更するコード例です。
実行中のプロセスの優先度を変更するときは、psutil という Python ライブラリを使用したらできました。
マルチプロセス処理時の作業を快適にする
ウィンドウズの場合です。
ふだん、優先度が「通常」になっているところを「低」に下げてあげます。
親プロセスの優先度を下げたら、マルチプロセス処理で現れる子プロセスも、優先度が下がった状態で開始されました。
これで、フルパワーのときに他のデバッグ作業などを始めても、さくさく快適になりました。
すぐにCPUを分けてくれました。
その間も、元のプログラムは空いているCPUを使い切ってくれたので、CPUの使用率は、常に100%でした。
それで、優先度を「通常」⇒「低」に下げたときの実行時間ですが、ログに記録した実行時間を見てきた限り、特に遅くなっている様子はありませんでした。
ほかの作業をしていなければ、「通常」のときとほぼ同じ時間で完了していました。
さて、決算分析システムでは、大量の XBRL を読み込んで数字を取り出したり、大量のグラフを描いたりしていました。
これらの処理は、マルチプロセス処理で実行して、すべてのCPUコアを動員していたのですが、そのあいだは他の作業が難しくなりました。
なので、プログラムの開始直後に「パイソンプロセスの優先度を下げる」というようなことをするようになりました。
psutil で優先度を変更
優先度の変更には、「psutil」というパイソン用モジュールを使用します。自分はピー・エス・ユーティルって呼んでいます。
公式サイトのドキュメントです。
(psutil.readthedocs.io) psutil documentation
インストール
pip でインストールします。
pip install psutil
一応、アンインストール方法です。
pip uninstall psutil
実行すると、削除前に「Proceed (y/n)?」と聞かれますので、「y」を入力してエンターキーを押します。これでアンインストール完了です。
優先度を「低」に下げるコード例
ナイスにアイドル・プライオリティー・クラスを渡したら「低」になりました。
設定が済めばインスタンス「p」は使わないので、削除しました。
import psutil
p = psutil.Process()
p.nice(psutil.IDLE_PRIORITY_CLASS)
del p
以下のように、もっと簡単に書いてもOKでした。
import psutil
psutil.Process().nice(psutil.IDLE_PRIORITY_CLASS)
決算分析システムでは、このようにして、プログラムの最初のほうで優先度を下げてから実行しています。
プロセスクラスとナイスメソッドの説明ページです。
(psutil) class psutil.Process(pid=None)
pid を省略すると、os.getpid() の PID が使われるとのことでした。
現在のプロセス ID に関する設定・情報取得が可能になりました。
(psutil) nice(value=None)
値を渡せば優先度を設定(省略すると優先度を取得)。
ほかの優先度に変えるコード例
優先度を高、通常以上、通常、通常以下、低に変えるコード例です。
優先度が変わっていく様子は、タスクマネージャーでも確認できました。
該当する「プロセス ID (PID)」を見ると、「基本優先度」列の表示が変わっていくはずです。
os.system('PAUSE')
は一時停止するためのコードです。
import os
import psutil
def main():
"""プロセスの優先度変更テスト"""
print('start\n')
# プロセスクラスのインスタンス作成
p = psutil.Process()
# 現在の「プロセスID」と「優先度」を表示
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
# 優先度: 高 (ハイ・プライオリティ)
p.nice(psutil.HIGH_PRIORITY_CLASS)
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
# 優先度: 通常以上 (アボーブ・ノーマル・プライオリティ)
p.nice(psutil.ABOVE_NORMAL_PRIORITY_CLASS)
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
# 優先度: 通常 (ノーマル・プライオリティ)
p.nice(psutil.NORMAL_PRIORITY_CLASS)
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
# 優先度: 通常以下 (ビロウ・ノーマル・プライオリティ)
p.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS)
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
# 優先度: 低 (アイドル・プライオリティ)
p.nice(psutil.IDLE_PRIORITY_CLASS)
print('PID: %s 優先度: %s\n' % (p.pid, p.nice()))
os.system('PAUSE')
del p
# ここに実行したい処理を書く
print('end')
return
if __name__ == '__main__':
main()
実行結果です。プロセス ID は実行するごとに変わりました。
start
PID: 5480 優先度: Priority.NORMAL_PRIORITY_CLASS
続行するには何かキーを押してください . . .
PID: 5480 優先度: Priority.HIGH_PRIORITY_CLASS
続行するには何かキーを押してください . . .
PID: 5480 優先度: Priority.ABOVE_NORMAL_PRIORITY_CLASS
続行するには何かキーを押してください . . .
PID: 5480 優先度: Priority.NORMAL_PRIORITY_CLASS
続行するには何かキーを押してください . . .
PID: 5480 優先度: Priority.BELOW_NORMAL_PRIORITY_CLASS
続行するには何かキーを押してください . . .
PID: 5480 優先度: Priority.IDLE_PRIORITY_CLASS
続行するには何かキーを押してください . . .
end
以上です
実行中のプロセスの関連記事です。
⇒ 【Python】実行中のプロセスの『コマンドライン引数』を取得するコード例
⇒ 【PowerShell】実行中のプロセスの『コマンドライン引数』を取得するコード例
マルチプロセス処理の関連記事です。