Как запустить часть скрипта (отдельной функции) в «фоновом режиме»? - PullRequest
0 голосов
/ 23 января 2019

Я запускаю скрипт Python на сервере, который имеет следующую базовую структуру (псевдокод):

for data_item in data_items:
    processed_result=process_data(data_item); #this takes time T0
    upload_result_to_site(processed_result) #this takes time T1

Основные ограничения:

  1. data_items (большой) список данных
  2. process_data() использует много процессора.
  3. upload_result_to_site() занимает очень мало процессора.
  4. T0 = 5*T1 (прибл.)

Теперь у меня ограниченное время на сервере, и я хотел бы использовать все это для интенсивного использования процессора process_data(), а не для upload_result(). к несчастью upload_result_to_site() необходимо.

Одним из решений было бы запустить:

upload_result_to_site(processed_result)

в фоновом режиме точно так же, как процессы можно запускать в фоновом режиме в Unix.

Я могу запустить весь сценарий в фоновом режиме (через os.popen3 или subprocess) или использовать демона. Но я хочу самое простое решение этой проблемы. Я не смог найти способ использовать подпроцесс для вызова только части скрипта (одна функция)

multiprocessing.Pool.map() можно использовать, но созданный им процесс должен быть присоединен и завершен в какой-то момент, иначе количество подпроцессов будет расти).

Есть ли простой способ сделать это?

Обновление: В настоящее время я использую этот обходной путь:

for data_item in data_items:
    processed_result=process_data(data_item); #this takes time T0
    os.system("myscript.py upload_result_to_site processed_result &")

где myscript.py - имя скрипта, а соответствующие обработчики присутствуют в __name__==__main__. (Теоретический) недостаток в том, что это, вероятно, работает только на Unix. Так как мой сервер работает под управлением Unix, это нормально для меня. Если у кого-то есть лучшее решение, пожалуйста, ответьте.

Ответы [ 2 ]

0 голосов
/ 23 января 2019

почему бы просто не сделать что-то подобное?

from multiprocessing import Pool

with Pool() as pool:
  for result in pool.imap_unordered(process_data, data_items)
    upload_result_to_site(result)

это приведет к запуску ряда процессов (Python делает предположение, основываясь на том, сколько у вас ядер), и process_data для выполнения в дочерних процессах. затем результаты возвращаются в основной процесс, где результаты загружаются по окончании обработки

также обратите внимание, что «данные» равны pickled при отправке и получении от дочерних заданий, поэтому должны быть совместимы с этим

0 голосов
/ 23 января 2019

Действительно долгосрочное простое решение - создать себе элементарные строительные блоки, которые вам нужны.Ваш сценарий делает две совершенно разные вещи.

«Естественным» решением было бы превратить ваш скрипт в модуль, который просто предлагает различные сервисы.

Затем вы можете написать один или несколько сценариев, которые импортируют этот модуль, и затем вы можете использовать popen3 / subprocess для простого вызова небольшого сценария, который, например, загружает единственный результат.

...