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 шт):

Автор решения: CrazyElf

Ну это же мультипроцессинг. Он запускает процессы. Т.е. да, как бы подгружается весь скрипт целиком в другой процесс, хотя из него и должна запуститься только одна функция. Попробуйте убрать всё кроме функции внутрь защитной проверки 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)))
→ Ссылка
Автор решения: Dmitrii Ogolikhin

@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. Для примера выше повторение не критично, но у меня изначально большой скрипт с большим количеством исходных данных, формируемых для выполнения функции, которую надо распараллелить.

→ Ссылка