Сделать 2 функции запущенными одновременно
Я пытаюсь заставить 2 функции работать одновременно.
def func1():
print 'Working'
def func2():
print 'Working'
func1()
func2()
Кто-нибудь знает как это сделать?
14 ответов
Сделай это:
from threading import Thread
def func1():
print 'Working'
def func2():
print 'Working'
if __name__ == '__main__':
Thread(target = func1).start()
Thread(target = func2).start()
Ответ о многопоточности хорош, но вам нужно быть более точным в отношении того, что вы хотите сделать.
Если у вас есть две функции, которые обе используют много ресурсов ЦП, многопоточность (в CPython), вероятно, ни к чему не приведет. Тогда вы, возможно, захотите взглянуть на многопроцессорный модуль или, возможно, захотите использовать jython/IronPython.
Если причина связана с производительностью процессора, вы могли бы даже реализовать что-то в (не поточном) C и получить гораздо большее ускорение, чем две параллельные вещи в python.
Без дополнительной информации найти хороший ответ нелегко.
Это может быть сделано элегантно с 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():
print("Working")
@ray.remote
def func2():
print("Working")
# Execute func1 and func2 in parallel.
ray.get([func1.remote(), func2.remote()])
Если func1()
а также func2()
чтобы вернуть результаты, вам нужно немного переписать приведенный выше код, заменив ray.get([func1.remote(), func2.remote()])
с:
ret_id1 = func1.remote()
ret_id2 = func1.remote()
ret1, ret2 = ray.get([ret_id1, ret_id2])
Существует ряд преимуществ использования Ray над многопроцессорным модулем или многопоточности. В частности, один и тот же код будет работать как на одной машине, так и на кластере машин.
Для получения дополнительных преимуществ Рэй см. Этот пост.
Я запустил этот код, чтобы проверить, выполняются ли функции одновременно:
#! /usr/bin/env python
import threading
from threading import Thread
import time
def time1():
time.sleep(1)
print time.time()
def time2():
time.sleep(1)
print time.time()
if __name__ == '__main__':
Thread(target = time1()).start()
Thread(target = time2()).start()
Вот что он возвращает:
1447425262.16
1447425263.16
Мне кажется, что функции запускаются одна за другой...?
Один вариант, который выглядит так, как будто две функции выполняются одновременно
время использует threading
модуль (пример в этом ответе).
Тем не менее, он имеет небольшую задержку, как официальная документация Python
страница описывает. Лучший модуль для использования multiprocessing
,
Также есть и другие модули Python, которые можно использовать для асинхронного выполнения (два куска кода работают одновременно). Чтобы получить некоторую информацию о них и помочь выбрать один, вы можете прочитать этот вопрос переполнения стека.
Комментарий от другого пользователя о threading
модуль
Он мог бы хотеть знать это из-за Глобальной Блокировки Интерпретатора
они не будут выполняться одновременно, даже если машина
Вопрос имеет несколько процессоров. http://wiki.python.org/moin/GlobalInterpreterLock
- Йонас Эльфстрем 2 июня 2010 года в 11:39
Цитата из документации о threading
модуль не работает
Детали реализации CPython: в CPython благодаря глобальному переводчику
Блокировка, только один поток может выполнять код Python одновременно (даже если
некоторые ориентированные на производительность библиотеки могут преодолеть это ограничение).Если вы хотите, чтобы ваше приложение лучше использовало вычислительные ресурсы многоядерных машин, рекомендуется использовать multiprocessing или concurrent.futures.ProcessPoolExecutor.
Тем не менее, многопоточность по-прежнему является подходящей моделью, если вы
хотите запустить несколько задач ввода-вывода одновременно.
Потоковый модуль работает одновременно, в отличие от многопроцессорных, но время немного не работает. Код ниже печатает "1" и "2". Они вызываются разными функциями соответственно. Я заметил, что при выводе на консоль у них будет немного другое время.
from threading import Thread
def one():
while(1 == num):
print("1")
time.sleep(2)
def two():
while(1 == num):
print("2")
time.sleep(2)
p1 = Thread(target = one)
p2 = Thread(target = two)
p1.start()
p2.start()
Вывод: (Обратите внимание, что промежуток для ожидания между печатью)
1
2
2
1
12
21
12
1
2
Не уверен, есть ли способ исправить это, или если это имеет значение вообще. Просто то, что я заметил.
Если вы также хотите дождаться завершения обеих функций:
from threading import Thread
def func1():
print 'Working'
def func2():
print 'Working'
# Define the threads and put them in an array
threads = [
Thread(target = self.func1),
Thread(target = self.func2)
]
# Func1 and Func2 run in separate threads
for thread in threads:
thread.start()
# Wait until both Func1 and Func2 have finished
for thread in threads:
thread.join()
Этот код ниже может запускать 2 функции параллельно:
from multiprocessing import Process
def test1():
print("Test1")
def test2():
print("Test2")
if __name__ == "__main__":
process1 = Process(target=test1)
process2 = Process(target=test2)
process1.start()
process2.start()
process1.join()
process2.join()
Результат:
И эти 2 набора кода ниже могут запускать 2 функции одновременно:
from threading import Thread
def test1():
print("Test1")
def test2():
print("Test2")
thread1 = Thread(target=test1)
thread2 = Thread(target=test2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
from operator import methodcaller
from multiprocessing.pool import ThreadPool
def test1():
print("Test1")
def test2():
print("Test2")
caller = methodcaller("__call__")
ThreadPool().map(caller, [test1, test2])
Результат:
И этот код ниже может запускать 2async
работает одновременно и асинхронно:
import asyncio
async def test1():
print("Test1")
async def test2():
print("Test2")
async def call_tests():
await asyncio.gather(test1(), test2())
asyncio.run(call_tests())
Результат:
Test1
Test2
Другой подход к одновременному запуску нескольких функций в python использует то, что я не мог видеть в ответах.
import asyncio
async def func1():
for _ in range(5):
print(func1.__name__)
await asyncio.sleep(0) # switches tasks every iteration.
async def func2():
for _ in range(5):
print(func2.__name__)
await asyncio.sleep(0)
tasks = [func1(), func2()]
await asyncio.gather(*tasks)
Вне:
func1
func2
func1
func2
func1
func2
func1
func2
func1
func2
[ ПРИМЕЧАНИЕ ]:
- Выше
asyncio
синтаксис действителен на python 3.7 и более поздних версиях - многопроцессорность против многопоточности против асинхронности
Попробуй это
from threading import Thread
def fun1():
print("Working1")
def fun2():
print("Working2")
t1 = Thread(target=fun1)
t2 = Thread(target=fun2)
t1.start()
t2.start()
Я думаю, что то, что вы пытаетесь передать, может быть достигнуто с помощью многопроцессорной обработки. Однако, если вы хотите сделать это через потоки, вы можете сделать это. Это может помочь
from threading import Thread
import time
def func1():
print 'Working'
time.sleep(2)
def func2():
print 'Working'
time.sleep(2)
th = Thread(target=func1)
th.start()
th1=Thread(target=func2)
th1.start()
тест с использованием APscheduler:
from apscheduler.schedulers.background import BackgroundScheduler
import datetime
dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2550) # 2.55 seconds from now testing start accuracy
def myjob1():
print('started job 1: ' + str(dt.now())[:-3]) # timed to millisecond because thats where it varies
time.sleep(5)
print('job 1 half at: ' + str(dt.now())[:-3])
time.sleep(5)
print('job 1 done at: ' + str(dt.now())[:-3])
def myjob2():
print('started job 2: ' + str(dt.now())[:-3])
time.sleep(5)
print('job 2 half at: ' + str(dt.now())[:-3])
time.sleep(5)
print('job 2 done at: ' + str(dt.now())[:-3])
print(' current time: ' + str(dt.now())[:-3])
print(' do job 1 at: ' + str(Future)[:-3] + '''
do job 2 at: ''' + str(Future)[:-3])
sched.add_job(myjob1, 'date', run_date=Future)
sched.add_job(myjob2, 'date', run_date=Future)
я получил эти результаты. что доказывает, что они работают одновременно.
current time: 2020-12-15 01:54:26.526
do job 1 at: 2020-12-15 01:54:29.072 # i figure these both say .072 because its 1 line of print code
do job 2 at: 2020-12-15 01:54:29.072
started job 2: 2020-12-15 01:54:29.075 # notice job 2 started before job 1, but code calls job 1 first.
started job 1: 2020-12-15 01:54:29.076
job 2 half at: 2020-12-15 01:54:34.077 # halfway point on each job completed same time accurate to the millisecond
job 1 half at: 2020-12-15 01:54:34.077
job 1 done at: 2020-12-15 01:54:39.078 # job 1 finished first. making it .004 seconds faster.
job 2 done at: 2020-12-15 01:54:39.091 # job 2 was .002 seconds faster the second test
мы можем сделать это, используя множественную обработку (используйте несколько процессоров) или многопоточность (используйте многопоточность одного процессора):
Пример многопоточности:
from threading import Thread
def fun_square(x):
x_square = x**2
print('x_square: ', x_square)
def x_pow_y(x,y):
x_pow_y = x**y
print('x_pow_y: ', x_pow_y)
def fun_qube(z):
z_qube = z*z*z
print('z_qube: ', z_qube)
def normal_fun():
print("Normal fun is working at same time...")
Thread(target = fun_square, args=(5,)).start() #args=(x,)
Thread(target = x_pow_y, args=(2,4,)).start() #args=(x,y,)
Thread(target = fun_qube(4)).start() #fun_qube(z)
Thread(target = normal_fun).start()
Пример многократной обработки:
from multiprocessing import Process
def fun_square(x):
x_square = x**2
print('x_square: ', x_square)
def x_pow_y(x,y):
x_pow_y = x**y
print('x_pow_y: ', x_pow_y)
def fun_qube(z):
z_qube = z*z*z
print('z_qube: ', z_qube)
def normal_fun():
print("Normal fun is working at same time...")
p1 = Process(target = fun_square, args=(5,)).start() #args=(x,)
p2 = Process(target = x_pow_y, args=(2,4,)).start() #args=(x,y,)
p3 = Process(target = fun_qube(5)).start() #fun_qube(z)
p4 = Process(target = normal_fun).start()
Я могу ошибаться, но: с этим фрагментом кода:
def function_sleep():
time.sleep(5)
start_time = time.time()
p1=Process(target=function_sleep)
p2=Process(target=function_sleep)
p1.start()
p2.start()
end_time = time.time()
Я потратил время, и я ожидал получить 5/6 секунд, в то время как всегда требуется двойное значение аргумента, переданного функции сна (в данном случае 10 секунд). В чем дело?
Извините, ребята, как упоминалось в предыдущем комментарии, необходимо вызвать «join ()». Это очень важно!