Resumo : neste tutorial, você aprenderá como usar Python ProcessPoolExecutor
para criar e gerenciar um pool de processos de forma eficaz.
Introdução à classe Python ProcessPoolExecutor
No tutorial anterior , você aprendeu como executar código em paralelo criando processos manualmente usando a Process
classe do multiprocessing
módulo. No entanto, criar processos manualmente não é eficiente.
Para gerenciar os processos com mais eficiência, você pode usar um pool de processos. Assim como um pool de threads , um pool de processos é um padrão para gerenciar processos automaticamente.
A ProcessPoolExecutor
classe do concurrent.futures
módulo permite criar e gerenciar um pool de processos.
Por exemplo, a ProcessPoolExecutor
classe usa o número de núcleos de CPU para criar um número otimizado de processos a serem criados.
O ProcessPoolExecutor
estende a Executor
classe que possui três métodos:
submit()
– despacha uma função para ser executada pelo processo e retorna um objeto Future.map()
– chamar uma função para um iterável de elementos.shutdown()
– desligue o executor.
Para liberar os recursos mantidos pelo executor, você precisa chamar o shutdown()
método explicitamente. Para desligar o executor automaticamente, você pode usar um gerenciador de contexto .
O Future
objeto representa um resultado agitado de uma operação assíncrona. Possui dois métodos principais para obter o resultado:
result()
– retornar o resultado da operação assíncrona.exception()
– retorna uma exceção que ocorreu durante a execução da operação assíncrona.
Exemplo de ProcessPoolExecutor em Python
O programa a seguir usa um pool de processos para criar miniaturas de imagens na images
pasta e salvá-las na thumbs
pasta.
import time
import os
from PIL import Image, ImageFilter
from concurrent.futures import ProcessPoolExecutor
filenames = [
'images/1.jpg',
'images/2.jpg',
'images/3.jpg',
'images/4.jpg',
'images/5.jpg',
]
def create_thumbnail(filename, size=(50,50), thumb_dir ='thumbs'):
# open the image
img = Image.open(filename)
# apply the gaussian blur filter
img = img.filter(ImageFilter.GaussianBlur())
# create a thumbnail
img.thumbnail(size)
# save the image
img.save(f'{thumb_dir}/{os.path.basename(filename)}')
# display a message
print(f'{filename} was processed...')
def main():
start = time.perf_counter()
with ProcessPoolExecutor() as executor:
executor.map(create_thumbnail, filenames)
finish = time.perf_counter()
print(f'It took {finish-start: .2f} second(s) to finish')
if __name__ == '__main__':
main()
Linguagem de código: Python ( python )
Saída:
images/5.jpg was processed...
images/4.jpg was processed...
images/3.jpg was processed...
images/2.jpg was processed...
images/1.jpg was processed...
It took 0.79 second(s) to finish
Linguagem de código: Python ( python )
Observe que para executar o programa, você precisa instalar o Pillow
que é uma biblioteca popular para processamento de imagens executando o comando pip pip install Pillow
.
Como funciona.
Primeiro, declare uma lista de arquivos para criação de miniaturas:
filenames = [
'images/1.jpg',
'images/2.jpg',
'images/3.jpg',
'images/4.jpg',
'images/5.jpg',
]
Linguagem de código: Python ( python )
Segundo, defina uma função que crie uma miniatura a partir de um arquivo de imagem e salve a saída na pasta de miniaturas:
def create_thumbnail(filename, size=(50,50), thumb_dir ='thumbs'):
# open the image
img = Image.open(filename)
# apply the gaussian blur filter
img = img.filter(ImageFilter.GaussianBlur())
# create a thumbnail
img.thumbnail(size)
# save the image
img.save(f'{thumb_dir}/{os.path.basename(filename)}')
# display a message
print(f'{filename} was processed...')
Linguagem de código: Python ( python )
Terceiro, crie um pool de processos e chame a create_thumbnail()
função para cada imagem especificada nos nomes dos arquivos:
with ProcessPoolExecutor() as executor:
executor.map(create_thumbnail, filenames)
Linguagem de código: Python ( python )
Resumo
- Use a classe Python ProcessPoolExecutor para criar e gerenciar um pool de processos automaticamente.