私は、進捗バーなどの並列進行情報で印刷する必要のある簡単なプロジェクトを持っています。並列印刷と書き込みロック
各バーには位置があり、バーの位置に応じて端末の書き込みカーソルが上下に移動します。
これはシリアルで実行するとうまく動作しますが、レースの問題で並行して印刷すると失敗します。私はmultiprocessing.Lock()
を使用しようとしましたが、無駄です。ここで
は私の現在のコードです:
from __future__ import division
import os, sys
import signal
from time import sleep
from multiprocessing import Pool, freeze_support, Lock
if os.name == 'nt':
import colorama # to support cursor up
colorama.init()
_term_move_up = '\x1b[A'
write_lock = Lock()
class simple_bar(object):
def __init__(self, iterable, desc='', position=0):
signal.signal(signal.SIGINT, signal.SIG_IGN) # handles keyboardinterrupt
self.iterable = iterable
self.total = len(iterable)
self.n = 0
self.position = position
self.desc = desc
self.display()
def __iter__(self):
for obj in self.iterable:
yield obj
self.update()
def update(self, n=1):
self.n += n
self.display()
def display(self, fp=None, width=79):
if not fp:
fp = sys.stdout
with write_lock:
fp.write('\n' * self.position)
l_part = self.desc + ': '
bar = l_part + '#' * int((self.n/self.total) * (width - len(l_part)))
fp.write('\r' + bar + ' ' * (width - len(bar)))
fp.write(_term_move_up * self.position)
fp.flush()
def progresser(n):
text = "progresser #{}".format(n)
for i in simple_bar(range(5000), desc=text, position=n):
sleep(0.001)
if __name__ == '__main__':
freeze_support()
L = list(range(3))
Pool(len(L)).map(progresser, L)
OK働くシリアル代替、これは上記の並列バージョンによって生成されなければならない正しい出力できます:
# Same code as above, except __main__
if __name__ == '__main__':
t_list = [simple_bar(range(5000), desc="progresser #{}".format(n), position=n) for n in xrange(3)]
for i in range(5000):
for t in t_list:
t.update()
を私は何見当がつかないうまくいかない。私は無事マルチプロセッシングに並列に印刷する方法を探して、理想的にはしかし場合スレッド安全い
のWindows 7上のPython 2.7.12を使用しています。
/編集:私はちょうど印刷前の待機(しかし、十分な大きさ)を入れた場合、興味深いことに、その後、バーが無事に印刷されています。私はこれが意味するものを結論を知らない
# ...
def display(self, fp=None, width=79):
if not fp:
fp = sys.stdout
with write_lock:
sleep(1) # this fixes the issue by adding a delay
fp.write('\n' * self.position)
l_part = self.desc + ': '
bar = l_part + '#' * int((self.n/self.total) * (width - len(l_part)))
fp.write('\r' + bar + ' ' * (width - len(bar)))
fp.write(_term_move_up * self.position)
fp.flush()
# ...
。
がわからない私が正しく理解して、このコードを試してみてくださいようです。一部のジョブを同時に処理し、その一部が完了したときにプログレスバーを印刷しますか?進行状況があなたのサブプロセスかあなたのメインプロセスによって印刷されるかどうかは重要ですか? – noxdafox
@noxdafoxはい、最初の質問には、2番目のはい、進捗状況は、サブプロセスから印刷する必要があります、これは問題です。メインプロセスからは、並行性がないため問題はありません。 – gaborous