Аннотация
Используйте процессы, а не потоки, потому что Python неэффективен с потоками, интенсивно использующими процессор, из-за GIL .
Два возможных решения для многопроцессорной обработки:
Это предпочтительно, если вы используете встроенное средство создания миниатюр (например, PIL
). Просто напишите функцию создания эскизов и запустите 12 параллельно. Когда один из процессов завершится, запустите другой в своем слоте.
Адаптировано из документации по Python, здесь скрипт должен использовать 12 ядер:
from multiprocessing import Process
import os
def info(title): # For learning purpose, remove when you got the PID\PPID idea
print title
print 'module:', __name__
print 'parent process:', os.getppid(),
print 'process id:', os.getpid()
def f(name): # Working function
info('function f')
print 'hello', name
if __name__ == '__main__':
info('main line')
processes=[Process(target=f, args=('bob-%d' % i,)) for i in range(12)]
[p.start() for p in processes]
[p.join() for p in processes]
Следуя комментарию соулмэна, вы можете воспользоваться предоставленным процессом pull.
Я адаптировал некоторый код из multiprocessing manual
. Обратите внимание, что вам, вероятно, следует использовать multiprocessing.cpu_count()
вместо 4
для автоматического определения количества процессоров.
from multiprocessing import Pool
import datetime
def f(x): # You thumbnail maker function, probably using some module like PIL
print '%-4d: Started at %s' % (x, datetime.datetime.now())
return x*x
if __name__ == '__main__':
pool = Pool(processes=4) # start 4 worker processes
print pool.map(f, range(25)) # prints "[0, 1, 4,..., 81]"
Что дает (обратите внимание, что распечатки строго не упорядочены!):
0 : Started at 2011-04-28 17:25:58.992560
1 : Started at 2011-04-28 17:25:58.992749
4 : Started at 2011-04-28 17:25:58.992829
5 : Started at 2011-04-28 17:25:58.992848
2 : Started at 2011-04-28 17:25:58.992741
3 : Started at 2011-04-28 17:25:58.992877
6 : Started at 2011-04-28 17:25:58.992884
7 : Started at 2011-04-28 17:25:58.992902
10 : Started at 2011-04-28 17:25:58.992998
11 : Started at 2011-04-28 17:25:58.993019
12 : Started at 2011-04-28 17:25:58.993056
13 : Started at 2011-04-28 17:25:58.993074
14 : Started at 2011-04-28 17:25:58.993109
15 : Started at 2011-04-28 17:25:58.993127
8 : Started at 2011-04-28 17:25:58.993025
9 : Started at 2011-04-28 17:25:58.993158
16 : Started at 2011-04-28 17:25:58.993161
17 : Started at 2011-04-28 17:25:58.993179
18 : Started at 2011-04-28 17:25:58.993230
20 : Started at 2011-04-28 17:25:58.993233
19 : Started at 2011-04-28 17:25:58.993249
21 : Started at 2011-04-28 17:25:58.993252
22 : Started at 2011-04-28 17:25:58.993288
24 : Started at 2011-04-28 17:25:58.993297
23 : Started at 2011-04-28 17:25:58.993307
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256,
289, 324, 361, 400, 441, 484, 529, 576]
Модуль subprocess
полезен для запуска внешних процессов и поэтому предпочтителен, если вы планируете использовать внешний инструмент для создания миниатюр, такой как imagemagick
'* convert
. Пример кода:
import subprocess as sp
processes=[sp.Popen('your-command-here', shell=True,
stdout=sp.PIPE, stderr=sp.PIPE) for i in range(12)]
Теперь итерируем процессы. Если какой-либо процесс завершен (с использованием subprocess.poll()
), удалите его и добавьте новый процесс в свой список.