Python: создание другой программы

У меня есть программа Python, из которой я создаю подпрограмму для обработки некоторых файлов, не задерживая основную программу. В настоящее время я использую bash для подпрограммы, запущенной с командой и двумя такими параметрами:

result = os.system('sub-program.sh file.txt file.txt &')

Это прекрасно работает, но я (в конце концов!) понял, что могу использовать Python для подпрограммы, что было бы гораздо предпочтительнее, поэтому я преобразовал его. Самый простой способ его нереста может быть:

result = os.system('python3 sub-program.py file.txt file.txt &')

Некоторые исследования показали несколько более сложных альтернатив, но у меня сложилось впечатление, что последним и наиболее одобренным методом является этот:

subprocess.Popen(["python3", "-u", "sub-program.py"])

Правильно ли я думаю, что это наиболее подходящий способ сделать это? Кто-нибудь порекомендует другой метод и почему? Просто было бы хорошо, так как я немного новичок в Python.

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

Дополнительные опции:

  • Отправить сообщение обратно из подпрограммы в основную программу.
  • Сделайте так, чтобы подпрограмма закрывалась, когда основная программа завершает работу.

person ChrisOfBristol    schedule 22.01.2016    source источник


Ответы (3)


Да, использование subprocess является рекомендуемым способом в соответствии с документацией:

Модуль подпроцессов предоставляет более мощные средства для создания новых процессов и получения их результатов; использование этого модуля предпочтительнее использования этой функции.

Однако subprocess.Popen может оказаться не тем, что вы ищете. В отличие от os.system вы создадите объект Popen, который соответствует подпроцессу, и вам нужно будет wait дождаться его завершения, fx:

proc = subprocess.Popen(["python3", "-u", "sub-program.py"])

do_something()

res = proc.wait()

Если вы хотите просто запустить программу и дождаться завершения, вам, вероятно, следует использовать вместо нее subprocess.run (или, может быть, subprocess.call, subprocess.check_call или subprocess.check_output).

person skyking    schedule 22.01.2016
comment
Я не хочу ждать, я хочу, чтобы он работал независимо, чтобы основная программа могла заниматься чем-то другим. - person ChrisOfBristol; 22.01.2016
comment
Просто используя код в моем примере выше, он не ждет, чего я и хочу. «Дополнительные опции», о которых я упомянул, можно посмотреть в другой день... - person ChrisOfBristol; 23.01.2016

Спасибо, скайкинг!

С

import subprocess

в начале основной программы это делает то, что я хочу:

with open('output.txt', 'w') as f:   
  subprocess.Popen([spawned.py, parameter1, parameter2], stdout = f)

Первая строка открывает файл для вывода из подпрограммы, запущенной во второй строке. Во второй строке в квадратных скобках содержится информация для подпрограммы — имя, за которым следуют два параметра. Параметры доступны в подпрограмме в sys.argv[1] и sys.argv[2]. После этого идут параметры подпроцесса - f говорит о выводе в текстовый файл, упомянутый выше.

person ChrisOfBristol    schedule 22.01.2016

Есть ли какая-то особая причина, по которой это должна быть совершенно другая программа? Почему бы просто не создать еще один процесс, который выполняет одну из функций, определенных в вашем скрипте?

Я предлагаю вам прочитать о многопроцессорности. В Python для этого есть модуль: https://docs.python.org/dev/library/multiprocessing.html

Здесь вы можете найти информацию о создании новых процессов, взаимодействии между ними и их синхронизации.

Однако имейте в виду, что если вы действительно хотите ускорить обработку файлов, вам следует использовать процессы вместо потоков (из-за некоторых ограничений в python потоки будут только замедлять вы вниз, что сбивает с толку).

Также посетите эту страницу: https://pymotw.com/2/multiprocessing/basics.html Там есть несколько примеров кода, которые вам очень помогут. Не забудьте этот охранник в своем скрипте:

if __name__ == '__main__':

Это очень важно ;)

person MarengoHue    schedule 22.01.2016
comment
Спасибо за ваши комментарии, но они в основном проходят мимо меня! 1 Есть ли какая-то особая причина... Я действительно не понимаю этого, я думаю, вы имеете в виду, что я могу запускать что-то асинхронно в моей основной программе 2 Я предлагаю вам прочитать Боюсь, я даже не понял первый абзац этого документа 3 Будьте осторожны, я не указал это как требование, но я думаю, что понимаю, что вы имеете в виду. - person ChrisOfBristol; 22.01.2016
comment
Буду ли я прав, думая, что: (1) мне не нужна отдельная программа, есть способ делать то, что я хочу, в основной программе. (3) Я должен использовать процесс, а не поток. Как называется этот метод и как убедиться, что он использует процесс, а не поток? Если бы вы могли сообщить мне, я смогу направить свои исследования, а не браться за изучение всех различных типов многопроцессорной обработки, - person ChrisOfBristol; 22.01.2016
comment
(1) да и (3) да. Возможно, я дал вам очень расплывчатую рекомендацию, поэтому вот ресурс, который, надеюсь, вам поможет: pymotw. com/2/multiprocessing/basics.html, так как здесь вы найдете несколько примеров кода, которые делают то, что вам нужно. Однако будьте осторожны: многопроцессорность/многопоточность — довольно сложные темы. - person MarengoHue; 24.01.2016
comment
Спасибо, это похоже на введение на уровне, который я понял бы с небольшим усилием. Метод, указанный в ответе 22 января в 21:21, работает, единственное, чего не хватает, — это возможности отправлять сообщения обратно из подпроцесса по мере выполнения задач. Я предполагаю, что многопроцессорная обработка, которую вы рекомендуете, сможет, но я использую графический интерфейс Glade, который, очевидно, имеет встроенный цикл, который ожидает ввода данных пользователем. Интересно, сможет ли он получать эти сообщения. Похоже, это становится все сложнее и сложнее. - person ChrisOfBristol; 26.01.2016
comment
Если метод работает, вы должны отметить его как ответ. (галочка слева) - person MarengoHue; 26.01.2016