В CPython многопоточность ограничена глобальной блокировкой интерпретатора - фактически только один поток одновременно может выполнять код Python.Так что многопоточность приносит вам пользу только в том случае, если:
вы выполняете обработку, которая не требует глобальной блокировки интерпретатора;или
вы тратите время на блокировку ввода-вывода.
Примеры (1) включают применение фильтра к изображению в Библиотека изображений Python , или поиск собственных значений матрицы в numpy .Примеры (2) включают ожидание ввода данных пользователем или ожидание завершения отправки данных сетевым подключением.
Таким образом, может ли ваш код быть ускорен с помощью потоков в CPython, зависит от того, что именно вы делаете в do_something
вызов.(Но если вы анализируете строку в Python, то очень маловероятно, что вы сможете ускорить это, запустив потоки.) Также следует учесть, что если вы начнете запускать потоки, тогда вы столкнетесь с проблемой синхронизации при записи результатов вцелевой файл.Нет никакой гарантии, что потоки будут завершены в том же порядке, в котором они были запущены, поэтому вам нужно позаботиться о том, чтобы выходные данные выходили в правильном порядке.
Вот реализация с максимальной резьбой, в которой есть потокидля чтения ввода, записи вывода и одного потока для обработки каждой строки.Только тестирование покажет вам, является ли это быстрее или медленнее, чем однопоточная версия (или версия Джанна только с тремя потоками).
from threading import Thread
from Queue import Queue
def process_file(f, source_filename, target_filename):
"""
Apply the function `f` to each line of `source_filename` and write
the results to `target_filename`. Each call to `f` is evaluated in
a separate thread.
"""
worker_queue = Queue()
finished = object()
def process(queue, line):
"Process `line` and put the result on `queue`."
queue.put(f(line))
def read():
"""
Read `source_filename`, create an output queue and a worker
thread for every line, and put that worker's output queue onto
`worker_queue`.
"""
with open(source_filename) as source:
for line in source:
queue = Queue()
Thread(target = process, args=(queue, line)).start()
worker_queue.put(queue)
worker_queue.put(finished)
Thread(target = read).start()
with open(target_filename, 'w') as target:
for output in iter(worker_queue.get, finished):
target.write(output.get())