実行中のPythonプログラムの優先度を下げる方法【psutil】

Python でプログラムの優先度を変更するコード例です。

実行中のプロセスの優先度を変更するときは、psutil という Python ライブラリを使用したらできました。

マルチプロセス処理時の作業を快適にする

ウィンドウズの場合です。

ふだん、優先度が「通常」になっているところを「低」に下げてあげます。

親プロセスの優先度を下げたら、マルチプロセス処理で現れる子プロセスも、優先度が下がった状態で開始されました

これで、フルパワーのときに他のデバッグ作業などを始めても、さくさく快適になりました。

すぐにCPUを分けてくれました。

その間も、元のプログラムは空いているCPUを使い切ってくれたので、CPUの使用率は、常に100%でした。

それで、優先度を「通常」⇒「低」に下げたときの実行時間ですが、ログに記録した実行時間を見てきた限り、特に遅くなっている様子はありませんでした。

ほかの作業をしていなければ、「通常」のときとほぼ同じ時間で完了していました。

さて、決算分析システムでは、大量の XBRL を読み込んで数字を取り出したり、大量のグラフを描いたりしていました。

これらの処理は、マルチプロセス処理で実行して、すべてのCPUコアを動員していたのですが、そのあいだは他の作業が難しくなりました。

なので、プログラムの開始直後に「パイソンプロセスの優先度を下げる」というようなことをするようになりました。

psutil で優先度を変更

優先度の変更には、「psutil」というパイソン用モジュールを使用します。自分はピー・エス・ユーティルって呼んでいます。

公式サイトのドキュメントです。

psutil documentation
https://psutil.readthedocs.io/en/latest/

インストール

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)

決算分析システムでは、このようにして、プログラムの最初のほうで優先度を下げてから実行しています。

プロセスクラスとナイスメソッドの説明ページです。

class psutil.Process(pid=None)
https://psutil.readthedocs.io/en/latest/#psutil.Process

pid を省略すると、os.getpid() の PID が使われるとのことでした。
現在のプロセス ID に関する設定・情報取得が可能になりました。

nice(value=None)
https://psutil.readthedocs.io/en/latest/#psutil.Process.nice

値を渡せば優先度を設定、省略すると優先度を取得

ほかの優先度に変えるコード例

優先度を高、通常以上、通常、通常以下、低に変えるコード例です。

優先度が変わっていく様子は、タスクマネージャーでも確認できました。

該当する「プロセス 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

以上です。

タイトルとURLをコピーしました