1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| import concurrent.futures as futures
from concurrent.futures import ThreadPoolExecutor as Pool
from PyQt5.QtCore import QObject, pyqtSignal
class Launcher(QObject):
update_done_ratio = pyqtSignal(float)
finished = pyqtSignal()
def __init__(self, parent=None, max_workers=2):
super().__init__(parent)
self.pending_fs = set()
self.done_fs = set()
self.pool = Pool(max_workers=max_workers)
self.finished.connect(lambda: self.pool.shutdown(wait=True))
def fs_callback(self, fs):
self.pending_fs.remove(fs)
self.done_fs.add(fs)
done = len(self.done_fs)
left = len(self.pending_fs)
self.update_done_ratio.emit(done / (done + left))
if not self.pending_fs:
self.finished.emit()
def submit(self, func):
fs = self.pool.submit(func)
self.pending_fs.add(fs)
fs.add_done_callback(self.fs_callback)
return fs
def abort(self):
for fs in self.pending_fs.copy():
fs.cancel()
def console_app(argv, iterfunc=None):
import sys
import signal
import time
from PyQt5.QtCore import QCoreApplication
class Helper(Launcher):
def __init__(self, max_workers=2):
super().__init__(max_workers=max_workers)
self.update_done_ratio.connect(self.update)
self.finished.connect(app.quit)
signal.signal(signal.SIGINT, self.signal_handler)
def update(self, ratio):
size = 50
sys.stdout.write('\r' + '%-*s|(%2.1f)' % (
size, '*' * int(ratio * size), ratio * 100))
sys.stdout.flush()
def signal_handler(self, signal, frame):
time.sleep(0.1)
print ('ctrl-C')
self.abort()
app = QCoreApplication([])
launcher = Helper()
for func in iterfunc:
launcher.submit(func)
app.exec_()
def qt_app(argv, iterfunc=None):
from PyQt5.QtWidgets import QApplication, QProgressDialog, QPushButton
def do_launch(functions):
launcher = Launcher()
dialog = QProgressDialog("En cours...", "Annuler", 0, 100)
launcher.update_done_ratio.connect(lambda x: dialog.setValue(100*x))
launcher.finished.connect(dialog.reset)
for func in functions:
launcher.submit(func)
dialog.exec_()
app = QApplication([])
functions = list(iterfunc) # histoire de pouvoir faire X start
btn = QPushButton('start')
btn.clicked.connect(lambda: do_launch(functions))
btn.show()
exit(app.exec_())
if __name__ == '__main__':
import time
import sys
COUNT = 10
def gen_func():
def task(x):
time.sleep(1)
return(x)
for z in range(COUNT):
yield lambda x=z: task(x)
if len(sys.argv) > 1:
console_app([], iterfunc=gen_func())
else:
qt_app([], iterfunc=gen_func()) |
Partager