#python #multithreading #text-files
#python #многопоточность #текстовые файлы
Вопрос:
Я пытаюсь прочитать файл на python (сканировать его строки и искать термины) и записать результаты — скажем, счетчики для каждого термина. Мне нужно сделать это для большого количества файлов (более 3000). Возможно ли сделать это многопоточным? Если да, то как?
Итак, сценарий выглядит следующим образом:
- Прочитайте каждый файл и просмотрите его строки
- Запишите счетчики в один и тот же выходной файл для всех файлов, которые я прочитал.
Второй вопрос: улучшает ли это скорость чтения / записи.
Надеюсь, это достаточно понятно. Спасибо,
Рон.
Ответ №1:
Я согласен с @aix, multiprocessing
это определенно правильный путь. Независимо от того, будете ли вы связаны с вводом-выводом — вы можете читать только так быстро, независимо от того, сколько параллельных процессов у вас запущено. Но может быть некоторое ускорение.
Рассмотрим следующее (input/ — это каталог, содержащий несколько файлов .txt из Project Gutenberg).
import os.path
from multiprocessing import Pool
import sys
import time
def process_file(name):
''' Process one file: count number of lines and words '''
linecount=0
wordcount=0
with open(name, 'r') as inp:
for line in inp:
linecount =1
wordcount =len(line.split(' '))
return name, linecount, wordcount
def process_files_parallel(arg, dirname, names):
''' Process each file in parallel via Poll.map() '''
pool=Pool()
results=pool.map(process_file, [os.path.join(dirname, name) for name in names])
def process_files(arg, dirname, names):
''' Process each file in via map() '''
results=map(process_file, [os.path.join(dirname, name) for name in names])
if __name__ == '__main__':
start=time.time()
os.path.walk('input/', process_files, None)
print "process_files()", time.time()-start
start=time.time()
os.path.walk('input/', process_files_parallel, None)
print "process_files_parallel()", time.time()-start
Когда я запускаю это на своей двухъядерной машине, наблюдается заметное (но не в 2 раза) ускорение:
$ python process_files.py
process_files() 1.71218085289
process_files_parallel() 1.28905105591
Если файлы достаточно малы, чтобы поместиться в памяти, и вам нужно выполнить много обработки, которая не связана с вводом-выводом, тогда вы должны увидеть еще лучшее улучшение.
Комментарии:
1. если у вас много файлов, я думаю, это создаст слишком много процессов. я получил этот process.process_files() 16.5930001736 process_files_parallel() 100.887000084
2. обратите внимание, что есть также pool.imap — соответствующий itertools.imap на python2 — если вы тоже ищете версию генератора. Это хорошая иллюстрация, кстати, хорошая работа.
Ответ №2:
Да, это должно быть возможно сделать параллельно.
Однако в Python трудно добиться параллелизма с несколькими потоками. По этой причине multiprocessing
это лучший выбор по умолчанию для параллельной работы.
Трудно сказать, какого ускорения вы можете ожидать. Это зависит от того, какую часть рабочей нагрузки можно будет выполнять параллельно (чем больше, тем лучше), и какую часть придется выполнять последовательно (чем меньше, тем лучше).
Комментарии:
1. «Однако в Python трудно добиться параллелизма с несколькими потоками» не могли бы вы указать причину этого? отличный ответ 1