Skip to content

Commit 35b87b1

Browse files
committed
[@boydfd] add tqdm multi-thread version.
0 parents  commit 35b87b1

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
__pycache__

test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import threading
2+
from concurrent.futures import ThreadPoolExecutor
3+
import time
4+
5+
from tqdm_multithread_factory import TqdmMultiThreadFactory
6+
7+
8+
def demo(factory, position, total):
9+
with factory.create(position, total) as progress:
10+
for _ in range(0, total, 5):
11+
progress.update(5)
12+
time.sleep(0.001 * (position % 5 + 1))
13+
14+
15+
with ThreadPoolExecutor(max_workers=20) as executor:
16+
tasks = range(100)
17+
lock = threading.Lock()
18+
multi_thread_factory = TqdmMultiThreadFactory()
19+
for i, url in enumerate(tasks, 1):
20+
executor.submit(demo, multi_thread_factory, i, 100)

tqdm_multithread.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import io
2+
import math
3+
import sys
4+
5+
from tqdm import tqdm
6+
7+
8+
class TqdmMultiThread(io.StringIO):
9+
def __init__(self, texts, id, total=100, lock=None):
10+
super().__init__()
11+
self.id = id
12+
self.lock = lock
13+
text = "progress #{}".format(id)
14+
with self.lock:
15+
self.texts = texts
16+
self.texts[id] = ''
17+
self.down()
18+
self.tqdm = tqdm(
19+
total=total,
20+
position=id,
21+
desc=text,
22+
file=self
23+
)
24+
25+
def update(self, *params):
26+
self.tqdm.update(*params)
27+
28+
def write(self, buf):
29+
self.with_lock_call(self._write, buf)
30+
31+
def _write(self, buf):
32+
buf = self.strip(buf)
33+
if buf:
34+
self.texts[self.id] = buf
35+
36+
@classmethod
37+
def strip(cls, buf):
38+
return buf.strip('\r\n\t\x1b[1A')
39+
40+
def flush(self):
41+
self.with_lock_call(self._flush)
42+
43+
def _flush(self):
44+
self.top()
45+
46+
for key in sorted(self.texts):
47+
sys.stdout.write(self.texts[key])
48+
self.down()
49+
50+
def up(self):
51+
self.print('\x1b[1A')
52+
53+
def down(self):
54+
self.print('\n')
55+
56+
def with_lock_call(self, func, *params):
57+
if self.lock:
58+
with self.lock:
59+
func(*params)
60+
else:
61+
func(*params)
62+
63+
def __exit__(self, exc_type, exc_val, exc_tb):
64+
self.tqdm.close()
65+
with self.lock:
66+
self.top()
67+
self.print(self.texts[self.id])
68+
self.bottom()
69+
del self.texts[self.id]
70+
71+
def print(self, text):
72+
sys.stdout.write(text)
73+
sys.stdout.flush()
74+
75+
def bottom(self):
76+
for i in range(self.get_length()):
77+
self.down()
78+
79+
def top(self):
80+
for i in range(self.get_length()):
81+
self.up()
82+
83+
def get_length(self):
84+
return len(self.texts)

tqdm_multithread_factory.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
import threading
3+
4+
from tqdm import tqdm
5+
6+
from tqdm_multithread import TqdmMultiThread
7+
8+
9+
class TqdmMultiThreadFactory:
10+
def __init__(self):
11+
self.texts = {}
12+
self.lock = threading.Lock()
13+
14+
def create(self, id, total):
15+
return TqdmMultiThread(self.texts, id, total, self.lock)

0 commit comments

Comments
 (0)