Python: одновременное выполнение нескольких функций

Я пытаюсь запустить две функции одновременно в Python. Я пробовал приведенный ниже код, который использует multiprocessing, но когда я запускаю код, вторая функция запускается только после того, как первая выполнена.

from multiprocessing import Process
def func1:
     #does something

def func2:
     #does something

if __name__=='__main__':
     p1 = Process(target = func1)
     p1.start()
     p2 = Process(target = func2)
     p2.start()

Ответ 1

Вы делаете это правильно.:)

Попробуйте запустить этот глупый фрагмент кода:

from multiprocessing import Process
import sys

rocket = 0

def func1():
    global rocket
    print 'start func1'
    while rocket < sys.maxint:
        rocket += 1
    print 'end func1'

def func2():
    global rocket
    print 'start func2'
    while rocket < sys.maxint:
        rocket += 1
    print 'end func2'

if __name__=='__main__':
    p1 = Process(target = func1)
    p1.start()
    p2 = Process(target = func2)
    p2.start()

Вы увидите, что он напечатает "start func1", а затем "start func2", а затем (очень) долгое время вы, наконец, увидите, что функции заканчиваются. Но они будут выполняться одновременно.

Поскольку процесс запускается некоторое время, вы можете даже увидеть "start func2" до "start func1".

Ответ 2

Это именно то, что мне нужно. Я знаю, что его не спрашивали, но я модифицировал код shashank, чтобы соответствовать Python 3 для всех остальных:)

from multiprocessing import Process
import sys

rocket = 0

def func1():
    global rocket
    print ('start func1')
    while rocket < sys.maxsize:
        rocket += 1
    print ('end func1')

def func2():
    global rocket
    print ('start func2')
    while rocket < sys.maxsize:
        rocket += 1
    print ('end func2')

if __name__=='__main__':
    p1 = Process(target=func1)
    p1.start()
    p2 = Process(target=func2)
    p2.start()

Замените sys.maxsize для числа, затем напечатайте (ракета), и вы увидите, что он подсчитывает один за раз. Перейдите к номеру и остановите

Ответ 3

Это очень хороший пример @Shashank. Я просто хочу сказать, что мне нужно было добавить join в конце, иначе два процесса не работали одновременно:

from multiprocessing import Process
import sys

rocket = 0

def func1():
    global rocket
    print 'start func1'
    while rocket < sys.maxint:
        rocket += 1
    print 'end func1'

def func2():
    global rocket
    print 'start func2'
    while rocket < sys.maxint:
        rocket += 1
    print 'end func2'

if __name__=='__main__':
    p1 = Process(target = func1)
    p1.start()
    p2 = Process(target = func2)
    p2.start()
    # This is where I had to add the join() function.
    p1.join()
    p2.join()

Кроме того, проверьте эту тему: Когда вызывать .join() для процесса?

Ответ 4

Вот еще одна версия, если необходимо запустить динамический список процессов. Я включаю два сценария оболочки, если вы хотите попробовать это:

t1.sh

for i in {1..10}
  do 
     echo "1... t.sh i:"$i
     sleep 1
  done

t2.sh

   for i in {1..3}
   do
       echo "2.. t2.sh i:"$i
       sleep 1
   done

np.py

import os
from multiprocessing import Process, Lock

def f(l, cmd):
    os.system(cmd)

if __name__ == '__main__':
    lock = Lock()

    for cmd in ['sh t1.sh', 'sh t2.sh']:
        Process(target=f, args=(lock, cmd)).start()

выход

1... t.sh i:1
2.. t2.sh i:1
1... t.sh i:2
2.. t2.sh i:2
1... t.sh i:3
2.. t2.sh i:3
1... t.sh i:4
1... t.sh i:5
1... t.sh i:6
1... t.sh i:7
1... t.sh i:8
1... t.sh i:9
1... t.sh i:10

"Блокировка", оставленная там, может быть получена перед задачей " l.acquire() " и l.release() после " l.release() "

Ответ 5

Это может быть сделано элегантно с Ray, системой, которая позволяет вам легко распараллеливать и распространять ваш код Python.

Чтобы распараллелить ваш пример, вам нужно определить свои функции с @ray.remote decorator, а затем вызвать их с помощью .remote.

import ray

ray.init()

# Define functions you want to execute in parallel using 
# the ray.remote decorator.
@ray.remote
def func1():
    #does something

@ray.remote
def func2():
    #does something

# Execute func1 and func2 in parallel.
ray.get([func1.remote(), func2.remote()])

Если func1() и func2() возвращают результаты, вам нужно переписать код следующим образом:

ret_id1 = func1.remote()
ret_id2 = func1.remote()
ret1, ret2 = ray.get([ret_id1, ret_id2])

Существует несколько преимуществ использования Ray по сравнению с многопроцессорным модулем. В частности, один и тот же код будет работать как на одной машине, так и на кластере машин. Для получения дополнительных преимуществ Рэй см. Этот пост.