Pythonでmultiprocessing（並列処理）を簡単に実装+可視化してくれるライブラリを作ってみた

# 前置き
Pythonで簡単に並列処理（multiprocessing）を行ってくれて、進捗を可視化してくれると助かると思ったため、それを実現するライブラリを作りました。
### 製作動機
面倒くさくて重たい処理をできれば並列処理したいなあ...ついでにその進捗もわかれば便利だなあ...
と思い、作りました。
またせっかくなのでtqdmではできないような、一行で並列処理とその進捗可視化できたら大変便利だと思ったのも動機の一つです。

https://github.com/Domzou-kun/prpl/blob/main/readme.md

この記事は基本的に**リポジトリのreadmeを日本語訳したもの**になりますが、Qiita用に編纂しています。

### QIita投稿動機
GitHubのraadmeは英語のため、日本人ユーザがわかりにくいと感じたため、日本語でも解説しておいた方が自身も便利であると感じたため、本記事を作成しました。

# prpl (progress-parallel)
`prpl`はPythonのライブラリであり、Pythonの標準ライブラリである`concurrent.futures`を用いた並列処理を簡単に行え、かつ進捗を可視化してくれるライブラリです。

# すぐに使いたい人向け
## インストール方法
```
pip install progress-parallel
```

## 使い方
使い方は2パターンあります

## 1. forループ単独で使用する方法
サンプルコードはこちら
```Python
t_list = list(range(0, 2500000))
for _ in prpl(t_list):
      pass
```
実行画面
![prpl test gif 10](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_run_10.gif?raw=true)

ごく一般的なfor文で進捗を確認したいときに使用できます。
prplにリストを渡すと、普通のfor文同様に値が順番に取り出されます
```Python
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 となる）

```Python
""" 従来の方法 """
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`を用いて並列処理したい場合、以下のようなコードになる。

```Python
""" 並列処理したい計算式 """
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 test gif 1](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_readme_sample_1.gif?raw=true)


## さらに詳しい使い方

以下のサンプルプログラムでは、適当な一次元リストと、そのリストの要素を計算する何かしらの関数を用いている。

- prplの最もシンプルな使い方
```Python
res = prpl(target_list=t_list, target_function=test_calc_func)
```
![prpl test gif 1](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_run_1.gif?raw=true)

- prplでCUI的なプログレスバーを用いる場合
```Python
res = prpl(target_list=t_list, target_function=test_calc_func, symbol="#", smpl=True)
```
![prpl test gif 4](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_run_4.gif?raw=true)

- タイマーモードを設定する場合
```Python
res = prpl(target_list=t_list, target_function=test_calc_func, timer=True)
```
![prpl test gif 7](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_run_7.gif?raw=true)

- プログレスバーの色を変える場合
```Python
res = prpl(target_list=t_list, target_function=test_calc_func, symbol="#", color="green")
```
![prpl test gif 6](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_run_6.gif?raw=true)

- 単一のプログレスバーを表示したい場合
```Python
res = prpl(target_list=t_list, target_function=test_calc_func, list_sep=1)
```
![prpl test gif sample 2](https://github.com/Domzou-kun/prpl/blob/main/docs/example_gif/prpl_readme_sample_2.gif?raw=true)


- 並列処理を行いたい関数に対して複数の引数を渡す場合
```Python
def multi_arguments_target_function(a,b,c,d):
  # 引数aがリストの要素として渡されてくるもの
  return a+b+c+d
```
```Python
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](https://github.com/Domzou-kun/prpl/issues)にまでよろしくお願いいたします。
こちらのQiitaのコメント欄でも結構です。できる限り対応いたします。