前置き
Pythonで簡単に並列処理(multiprocessing)を行ってくれて、進捗を可視化してくれると助かると思ったため、それを実現するライブラリを作りました。
製作動機
面倒くさくて重たい処理をできれば並列処理したいなあ...ついでにその進捗もわかれば便利だなあ...
と思い、作りました。
またせっかくなのでtqdmではできないような、一行で並列処理とその進捗可視化できたら大変便利だと思ったのも動機の一つです。
この記事は基本的にリポジトリのreadmeを日本語訳したものになりますが、Qiita用に編纂しています。
QIita投稿動機
GitHubのraadmeは英語のため、日本人ユーザがわかりにくいと感じたため、日本語でも解説しておいた方が自身も便利であると感じたため、本記事を作成しました。
prpl (progress-parallel)
prpl
はPythonのライブラリであり、Pythonの標準ライブラリであるconcurrent.futures
を用いた並列処理を簡単に行え、かつ進捗を可視化してくれるライブラリです。
すぐに使いたい人向け
インストール方法
pip install progress-parallel
使い方
使い方は2パターンあります
1. forループ単独で使用する方法
サンプルコードはこちら
t_list = list(range(0, 2500000))
for _ in prpl(t_list):
pass
ごく一般的なfor文で進捗を確認したいときに使用できます。
prplにリストを渡すと、普通のfor文同様に値が順番に取り出されます
t_list = list(range(0, 5))
for i in prpl(t_list):
print(i)
# 実行結果
# >> 0
# >> 1
# >> 2
# >> 3
# >> 4
2. マルチスレッドによる並列処理で使用する方法
マルチスレッドで使用する場合、並列処理したい処理を関数にする必要があります。
以下では、従来のfor文の方法を用いて、prplにて並列処理を行う方法を説明します。
サンプルコードとして、(渡された値^(渡された値))^2という計算を行います。
(例:3を渡されるとすると、(3^3)^2 = 27^2 = 729 となる)
""" 従来の方法 """
calculation_result = []
target_list = list(range(0, 100000))
for target_var in target_list:
calc_answer = (target_var**target_var)**2 # 計算式
calculation_result.append(calc_answer)
この処理をprpl
を用いて並列処理したい場合、以下のようなコードになる。
""" 並列処理したい計算式 """
def target_function(target_var):
calc_answer = (target_var**target_var)**2 # 計算式
return calc_answer
""" prplの呼び出し """
from prpl import prpl
target_list = list(range(0, 100000))
calculation_result = prpl(target_list, target_function) # prpl
実際に実行した場合の計算時間の比較は以下のようになる。
単純ではあるがおおよそ2倍程度早く計算ができることとなった。
さらに詳しい使い方
以下のサンプルプログラムでは、適当な一次元リストと、そのリストの要素を計算する何かしらの関数を用いている。
- prplの最もシンプルな使い方
res = prpl(target_list=t_list, target_function=test_calc_func)
- prplでCUI的なプログレスバーを用いる場合
res = prpl(target_list=t_list, target_function=test_calc_func, symbol="#", smpl=True)
- タイマーモードを設定する場合
res = prpl(target_list=t_list, target_function=test_calc_func, timer=True)
- プログレスバーの色を変える場合
res = prpl(target_list=t_list, target_function=test_calc_func, symbol="#", color="green")
- 単一のプログレスバーを表示したい場合
res = prpl(target_list=t_list, target_function=test_calc_func, list_sep=1)
- 並列処理を行いたい関数に対して複数の引数を渡す場合
def multi_arguments_target_function(a,b,c,d):
# 引数aがリストの要素として渡されてくるもの
return a+b+c+d
args_dict = {
"b": 2,
"c": 3,
"d": 4
}
res = prpl(target_list=t_list, target_function=multi_arguments_target_function, args=args_dict)
他の引数は必ずdict
型で渡す必要があることに注意
引数一覧
prpl
で設定できる引数は次のようになっています。
result_list = prpl( # 必ずreturnではリスト型を返します。
target_list, # 必須の引数
### 並列処理に流したいリスト
target_function, # 必要な場合がある引数
### 並列処理を行い関数
### forループで使用したい場合は必要ではない
args,
### 並列処理を行いたい関数に複数の引数を渡したい場合に必要
list_sep,
### スレッドの分割数
### デフォルトでは5に設定
checkpoint,
### 進捗を確認するタイミングの数
### デフォルトでは10に設定
title,
### プログレスバーのタイトル
### デフォルトではターゲットとなる関数の名前に自動で設定
symbol,
### プログレスバーのマーク
symbol_c,
### プログレスバーの長さ
### デフォルトでは50に設定
smpl,
### シンプルモードへの設定の有無
### defaultではFalse
timer,
### タイマーの有無
### シンプルモードがTrueの場合は使用できません
color
### プログレスバーのマークcolorの変更
)
注意事項
Pythonで有名なプログレスバーを表示できるライブラリであるtqdm
と併用して使用することはできません。
同時に実行するプログラムでprpl
とtqdm
をimportすることはできますが、どちらかしか正しく動作できません。
これはプログレスバーを表紙されるために、CSIsequenceを用いてコンソール画面を制御しているためです。
tqdmもprplもほぼ同様の手法にてコンソールをエスケープシーケンスにて制御していますが、互いに設定が微妙に異なり競合するため、どちらかの設定が優先されて、同時に使用すると画面が著しく乱れることが確認済みです
最後に
もし使ってみて何か不具合などがあれば、GItHubのissueにまでよろしくお願いいたします。
こちらのQiitaのコメント欄でも結構です。できる限り対応いたします。