Я не смог реализовать предложение здесь: Применение двух функций к двум спискам одновременно.
Я предполагаю, что это потому, что модуль импортируется другим модулем, и поэтому моя Windows порождает несколько процессов python?
Мой вопрос: как я могу использовать код ниже без if if __name__ == "__main__":
args_m = [(mortality_men, my_agents, graveyard, families, firms, year, agent) for agent in males]
args_f = [(mortality_women, fertility, year, families, my_agents, graveyard, firms, agent) for agent in females]
with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
p.map_async(process_males, args_m)
p.map_async(process_females, args_f)
Оба process_males
и process_females
являются fuctions.
args_m, args_f
являются итераторами
Кроме того, мне не нужно ничего возвращать. Агенты - это экземпляры классов, которые нуждаются в обновлении.
Идея if __name__ == '__main__':
заключается в том, чтобы избежать бесконечного нереста процесса.
При травлении функции, определенной в вашем основном script, python должен выяснить, какая часть вашего основного script - это код функции. В основном это запустит ваш script. Если ваш код, создающий Pool
, находится в том же script и не защищен "if main", то, попытавшись импортировать эту функцию, вы попытаетесь запустить еще один Pool
, который попытается запустить еще один Pool
....
Таким образом, вы должны отделить определения функций от фактического основного script:
from multiprocessing import Pool
# define test functions outside main
# so it can be imported withou launching
# new Pool
def test_func():
pass
if __name__ == '__main__':
with Pool(4) as p:
r = p.apply_async(test_func)
... do stuff
result = r.get()
p.apply_async(other_module.test_func)
? Дело в том, что я не могу вызвать test_func, пока не получу данные. Затем мне нужно звонить это неоднократно, каждый месяц. Я попробую дальше ... Спасибо.
test_func
в другой модуль без проблем. Проблемы возникают для функций, которые определены в модуле __main__
. Функции, переданные в apply_async
должны быть просто присоединены к обычному модулю.
Причина, по которой вам нужно защитить код многопроцессорности в if __name__ == "__main__"
, заключается в том, что вы не хотите, чтобы он снова запускался в дочернем процессе. Это может произойти в Windows, где интерпретатору необходимо перезагрузить все его состояние, поскольку нет системного вызова fork
, который скопирует адресное пространство родительского процесса. Но вам нужно использовать его только там, где код должен работать на верхнем уровне, так как вы находитесь в главном script. Это не единственный способ защитить ваш код.
В вашем конкретном случае, я думаю, вы должны поместить код multiprocessing
в функцию. Это не будет выполняться в дочернем процессе, если никто не вызывает функцию, когда это не должно. Ваш основной модуль может импортировать модуль, а затем вызвать функцию (возможно, из блока if __name__ == "__main__"
).
Это должно быть примерно так:
some_module.py:
def process_males(x):
...
def process_females(x):
...
args_m = [...] # these could be defined inside the function below if that makes more sense
args_f = [...]
def do_stuff():
with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
p.map_async(process_males, args_m)
p.map_async(process_females, args_f)
main.py:
import some_module
if __name__ == "__main__":
some_module.do_stuff()
В вашем реальном коде вам может понадобиться передать некоторые аргументы или получить возвращаемое значение из do_stuff
(которому также должно быть дано более описательное имя, чем общее, которое я использовал в этом примере).
main.py
Моя полная программа выглядит следующим образом: main.py
инициирует процесс. затем вызывается параметризация, затем загружаются или создаются агенты, затем выполняется модуль итерации времени. Время итерации вызывает running_month
где мне нужно do_stuff()
. Кроме того, при многократном моделировании я вызываю main.py 100 раз. В итоге, порядок событий не позволяет мне иметь do_stuff внутри, если имя ...
if __name__ == "__main__"
в main.py (или из других функций).
__main__
, вместо использования кода модуля верхнего уровня.