Динамическое обновление печати многопроцессорной или многопоточности в Python
Я реализовал многопроцессорный загрузчик. Как мне распечатать строку состояния (полная скорость, скорость загрузки), которая может автоматически обновляться в другой части на терминале.
Как это:
499712 [6.79%] 68k/s // keep refreshing
122712 [16.79%] 42k/s // different process/thread
99712 [56.32%] 10k/s
код:
download(...)
...
f = open(tmp_file_path, 'wb')
print "Downloading: %s Bytes: %s" % (self.file_name, self.file_size)
file_size_dl = 0
block_sz = 8192
start_time = time.time()
while True:
buffer = self.opening.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
end_time = time.time()
cost_time = end_time - start_time
if cost_time == 0:
cost_time = 1
status = "\r%10d [%3.2f%%] %3dk/s" % (file_size_dl,
file_size_dl * 100. / self.file_size,
file_size_dl * 100. / 1024 / 1024 / cost_time)
print status,
sys.stdout.flush()
f.close()
DownloadProcess наследует класс Process и вызывает метод загрузки.
Я использую очередь для хранения URL. Здесь начинается процесс
...
for i in range(3):
t = DownloadProcess(queue)
t.start()
for url in urls:
queue.put(url)
queue.join()
1 ответ
Ниже приведена демонстрация, в которой реализована многопоточность и многопоточность. Чтобы попробовать один или другой, просто раскомментируйте строки импорта в верхней части кода. Если у вас есть индикатор выполнения в одной строке, вы можете использовать технику печати '\r', чтобы переместить курсор назад к началу строки. Но если вы хотите иметь многострочные индикаторы выполнения, вам придется немного повеселиться. Я просто очищал экран каждый раз, когда хотел напечатать индикаторы выполнения. Посмотрите на консольный вывод статьи по Unix в Python, он очень помог мне в создании приведенного ниже кода. Он показывает обе техники. Вы также можете попробовать библиотеку curses, которая является частью стандартной библиотеки python. Вопрос Многострочные индикаторы выполнения задает аналогичную вещь. Основной поток / процесс порождает дочерние потоки, которые выполняют работу, и сообщают о своем прогрессе обратно основному потоку, используя очередь. Я настоятельно рекомендую использовать очереди для взаимодействия между процессами и потоками. Затем основной поток отображает ход выполнения и ждет, пока все дочерние элементы завершат выполнение, прежде чем покинуть себя.
код
import time, random, sys, collections
from multiprocessing import Process as Task, Queue
#from threading import Thread as Task
#from Queue import Queue
def download(status, filename):
count = random.randint(5, 30)
for i in range(count):
status.put([filename, (i+1.0)/count])
time.sleep(0.1)
def print_progress(progress):
sys.stdout.write('\033[2J\033[H') #clear screen
for filename, percent in progress.items():
bar = ('=' * int(percent * 20)).ljust(20)
percent = int(percent * 100)
sys.stdout.write("%s [%s] %s%%\n" % (filename, bar, percent))
sys.stdout.flush()
def main():
status = Queue()
progress = collections.OrderedDict()
workers = []
for filename in ['test1.txt', 'test2.txt', 'test3.txt']:
child = Task(target=download, args=(status, filename))
child.start()
workers.append(child)
progress[filename] = 0.0
while any(i.is_alive() for i in workers):
time.sleep(0.1)
while not status.empty():
filename, percent = status.get()
progress[filename] = percent
print_progress(progress)
print 'all downloads complete'
main()
демонстрация