Eu pesquisei primeiro e não consegui encontrar uma resposta para minha pergunta. Estou tentando executar várias funções em paralelo em Python.
Eu tenho algo assim:
files.py
import common #common is a util class that handles all the IO stuff
dir1 = 'C:\folder1'
dir2 = 'C:\folder2'
filename = 'test.txt'
addFiles = [25, 5, 15, 35, 45, 25, 5, 15, 35, 45]
def func1():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir1)
c.getFiles(dir1)
time.sleep(10)
c.removeFiles(addFiles[i], dir1)
c.getFiles(dir1)
def func2():
c = common.Common()
for i in range(len(addFiles)):
c.createFiles(addFiles[i], filename, dir2)
c.getFiles(dir2)
time.sleep(10)
c.removeFiles(addFiles[i], dir2)
c.getFiles(dir2)
Eu quero chamar func1 e func2 e executá-los ao mesmo tempo. As funções não interagem entre si ou no mesmo objeto. No momento, tenho que esperar que func1 termine antes que func2 comece. Como faço algo como abaixo:
process.py
from files import func1, func2
runBothFunc(func1(), func2())
Quero ser capaz de criar os dois diretórios quase ao mesmo tempo, porque a cada minuto estou contando quantos arquivos estão sendo criados. Se o diretório não estiver lá, isso prejudicará meu tempo.
Respostas:
Você pode usar
threading
oumultiprocessing
.Devido às peculiaridades do CPython ,
threading
é improvável que alcance o verdadeiro paralelismo. Por esse motivo,multiprocessing
geralmente é uma aposta melhor.Aqui está um exemplo completo:
A mecânica de iniciar / juntar processos filho pode ser facilmente encapsulada em uma função ao longo das linhas de
runBothFunc
:fonte
Isso pode ser feito elegantemente com o Ray , um sistema que permite paralelizar e distribuir facilmente seu código Python.
Para paralelizar seu exemplo, você precisa definir suas funções com o
@ray.remote
decorador e, em seguida, invocá-las com.remote
.Se você passar o mesmo argumento para ambas as funções e o argumento for grande, uma maneira mais eficiente de fazer isso é usando
ray.put()
. Isso evita que o grande argumento seja serializado duas vezes e crie duas cópias de memória dele:Se
func1()
efunc2()
retornar resultados, você precisará reescrever o código da seguinte maneira:Existem várias vantagens em usar o Ray em vez do módulo de multiprocessamento . Em particular, o mesmo código será executado em uma única máquina, bem como em um cluster de máquinas. Para obter mais vantagens do Ray, consulte esta postagem relacionada .
fonte
Se suas funções estão principalmente fazendo trabalho de E / S (e menos trabalho de CPU) e você tem Python 3.2+, você pode usar um ThreadPoolExecutor :
Se suas funções estão fazendo principalmente trabalho de CPU (e menos trabalho de E / S) e você tem Python 2.6+, você pode usar o módulo de multiprocessamento :
fonte
Se você é um usuário do Windows e usa python 3, então esta postagem irá ajudá-lo a fazer programação paralela em python. Quando você executa a programação de pool de uma biblioteca de multiprocessamento normal, obterá um erro em relação à função principal em seu programa. Isso ocorre porque o Windows não tem funcionalidade fork (). O post abaixo está dando uma solução para o problema mencionado.
http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html
Como estava usando o python 3, mudei o programa um pouco assim:
Após esta função, o código do problema acima também é alterado um pouco assim:
E obtive o resultado como:
Estou pensando que este post pode ser útil para alguns dos usuários do Windows.
fonte
Não há como garantir que duas funções serão executadas em sincronia uma com a outra, o que parece ser o que você deseja fazer.
O melhor que você pode fazer é dividir a função em várias etapas e, em seguida, esperar que ambas terminem em pontos críticos de sincronização usando
Process.join
como as menções de resposta do @aix.Isto é melhor que
time.sleep(10)
porque você não pode garantir os tempos exatos. Com a espera explicitamente, você está dizendo que as funções devem ser executadas naquela etapa antes de passar para a próxima, em vez de presumir que será feito em 10ms, o que não é garantido com base no que mais está acontecendo na máquina.fonte
Parece que você tem uma única função que precisa chamar em dois parâmetros diferentes. Isso pode ser feito elegantemente usando uma combinação de
concurrent.futures
emap
com Python 3.2+Agora, se sua operação for vinculada a IO, você pode usar o
ThreadPoolExecutor
como tal:Observe como
map
é usado aqui paramap
sua função para a lista de argumentos.Agora, se sua função for limitada pela CPU, você pode usar
ProcessPoolExecutor
Se não tiver certeza, você pode simplesmente tentar os dois e ver qual oferece melhores resultados.
Finalmente, se quiser imprimir seus resultados, você pode simplesmente fazer o seguinte:
fonte