Investigué primero y no pude encontrar una respuesta a mi pregunta. Estoy tratando de ejecutar varias funciones en paralelo en Python.
Tengo algo como esto:
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)
Quiero llamar a func1 y func2 y hacer que se ejecuten al mismo tiempo. Las funciones no interactúan entre sí ni en el mismo objeto. Ahora mismo tengo que esperar a que termine func1 antes de que comience func2. ¿Cómo hago algo como a continuación?
process.py
from files import func1, func2
runBothFunc(func1(), func2())
Quiero poder crear ambos directorios casi al mismo tiempo porque cada minuto estoy contando cuántos archivos se están creando. Si el directorio no está allí, perderá el tiempo.
Respuestas:
Puede usar
threading
omultiprocessing
.Debido a las peculiaridades de CPython ,
threading
es poco probable que logre un verdadero paralelismo. Por esta razón,multiprocessing
generalmente es una mejor apuesta.Aquí tienes un ejemplo completo:
La mecánica de iniciar / unir procesos secundarios se puede encapsular fácilmente en una función a lo largo de las líneas de su
runBothFunc
:fuente
Esto se puede hacer elegantemente con Ray , un sistema que le permite paralelizar y distribuir fácilmente su código Python.
Para paralelizar su ejemplo, necesitaría definir sus funciones con el
@ray.remote
decorador y luego invocarlas con.remote
.Si pasa el mismo argumento a ambas funciones y el argumento es grande, una forma más eficiente de hacerlo es usando
ray.put()
. Esto evita que el gran argumento se serialice dos veces y cree dos copias de memoria del mismo:Si
func1()
yfunc2()
devuelve resultados, debe volver a escribir el código de la siguiente manera:Hay una serie de ventajas de utilizar Ray sobre el módulo de multiprocesamiento . En particular, el mismo código se ejecutará en una sola máquina, así como en un grupo de máquinas. Para obtener más ventajas de Ray, consulte esta publicación relacionada .
fuente
Si sus funciones están principalmente haciendo trabajo de E / S (y menos trabajo de CPU) y tiene Python 3.2+, puede usar un ThreadPoolExecutor :
Si sus funciones hacen principalmente trabajo de CPU (y menos trabajo de E / S) y tiene Python 2.6+, puede usar el módulo de multiprocesamiento :
fuente
Si es un usuario de Windows y usa Python 3, entonces esta publicación lo ayudará a hacer programación paralela en Python. Cuando ejecute una programación de grupo de biblioteca multiprocesamiento habitual, obtendrá un error con respecto a la función principal en su programa. Esto se debe al hecho de que Windows no tiene la funcionalidad fork (). La siguiente publicación ofrece una solución al problema mencionado.
http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html
Como estaba usando Python 3, cambié el programa un poco así:
Después de esta función, el código de problema anterior también se cambia un poco así:
Y obtuve la salida como:
Creo que esta publicación puede ser útil para algunos usuarios de Windows.
fuente
No hay forma de garantizar que dos funciones se ejecuten en sincronía entre sí, lo que parece ser lo que desea hacer.
Lo mejor que puede hacer es dividir la función en varios pasos, luego esperar a que ambos terminen en los puntos críticos de sincronización usando
Process.join
las menciones de respuesta de like @ aix.Esto es mejor que
time.sleep(10)
porque no puede garantizar tiempos exactos. Con la espera explícita, está diciendo que las funciones deben realizarse ejecutando ese paso antes de pasar al siguiente, en lugar de asumir que se realizará dentro de los 10 ms, lo que no está garantizado en función de lo que esté sucediendo en la máquina.fuente
Parece que tiene una sola función a la que necesita llamar en dos parámetros diferentes. Esto se puede hacer elegantemente usando una combinación de
concurrent.futures
ymap
con Python 3.2+Ahora, si su operación está vinculada a IO, entonces puede usar el
ThreadPoolExecutor
como tal:Tenga en cuenta cómo
map
se usa aquí paramap
su función para la lista de argumentos.Ahora, si su función está vinculada a la CPU, entonces puede usar
ProcessPoolExecutor
Si no está seguro, simplemente puede probar ambos y ver cuál le da mejores resultados.
Finalmente, si está buscando imprimir sus resultados, simplemente puede hacer esto:
fuente