Multiprocessing pool запускает весь скрипт вместо одной функции
Я использую Spyder 5.0.3 с Python 3.7.9 (Windows 7) на одном компьютере и Spyder 5.2.9 с Python 3.7.9 (Windows 10) на другом.
На моём компьютере при использовании multiprocessor.pool всё работает как мне нужно (пример будет ниже). На другом, такое ощущение, что выполняется параллельно не одна функция, а весь скрипт.
Пример. Есть скрипт.
import multiprocessing as mp
def example(num):
return num**2
print('Hello')
n_proc = 4
numbers = [0,1,2,3]
if __name__ == "__main__":
pool = mp.Pool(processes = n_proc)
print(pool.map(example,numbers))
pool.close()
pool.join()
На моём компьютере вывод такой:
Hello
[0, 1, 4, 9]
На другом:
Hello
[0, 1, 4, 9]
Hello
Hello
Hello
Т.е., будто весь скрипт несколько раз запускается. Для интереса попробовал запустить скрипт через командную строку напрямую без Spyder. На обоих компьютерах получил вывод:
Hello
[0, 1, 4, 9]
Hello
Hello
Hello
Таким образом, у меня три вопроса: 1). Правильно ли я понимаю, что второй вариант вывода всё-таки более правильный? 2). Почему при запуске скрипта через Spyder вывод отличается от того, что можно получается через командную строку? 3). Как малой кровью исправить проблему/переделать скрипт, причём так, чтобы это решение работало на как можно большем количестве компьютеров (Windows)? Я писал и отлаживал прогу на своём компе и работала она так как мне надо. Я не был готов к тому, что для каждого компа придётся переделывать скрипт) Задача ещё осложняется тем, что перед записью самой функции, которая должна параллельно выполняться, у меня формируются исходные данные для неё. Может, есть уже какие-то готовые решения для такой задачи, которые я не знаю? Спасибо.
Ответы (2 шт):
Ну это же мультипроцессинг. Он запускает процессы. Т.е. да, как бы подгружается весь скрипт целиком в другой процесс, хотя из него и должна запуститься только одна функция. Попробуйте убрать всё кроме функции внутрь защитной проверки if __name__ == "__main__":, она нужна не только при выносе кода в библиотеки, на windows она нужна ещё и для того, чтобы в запущенных дополнительных процессах не запускался лишний код:
import multiprocessing as mp
def example(num):
return num**2
if __name__ == "__main__":
print('Hello')
n_proc = 4
numbers = [0,1,2,3]
pool = mp.Pool(processes = n_proc)
print(pool.map(example,numbers))
pool.close()
pool.join()
Я понял, что у вас где-то и без этого работает правильно, но если хотите, чтобы правильно работало везде - делайте как правильно.
Update: Пример передачи нескольких параметров в функцию:
import multiprocessing as mp
def example(num, aleop):
return num**2
if __name__ == "__main__":
print('Hello')
n_proc = 4
numbers = [0,1,2,3]
aleops = [1,1,2,2]
with mp.Pool(processes = n_proc) as pool:
print(pool.starmap(example,zip(numbers,aleops)))
@Roman Konoval, @CrazyElf, я имею ввиду такой вариант: Допустим, я хочу перед объявлением функции задать степень в которую возвожу уже в самой функции. Типа такого:
import multiprocessing as mp
#Блок кода, определяющий степень (переменная aleop) для функции example
def example(num):
return num**aleop
if __name__ == "__main__":
print('Hello')
n_proc = 4
numbers = [0,1,2,3]
pool = mp.Pool(processes = n_proc)
print(pool.map(example,numbers))
pool.close()
pool.join()
Вот этот блок кода будет повторяться при выполнении каждого процесса, получается.
Если этот блок кода загнать в if __name__ == "__main__":, то компилятор, естественно, ругается на отсутствие переменной aleop.
Для примера выше повторение не критично, но у меня изначально большой скрипт с большим количеством исходных данных, формируемых для выполнения функции, которую надо распараллелить.