Подтвердить что ты не робот

Запустить полностью независимый процесс

Я хотел инициировать процесс с моего python script (main.py), в частности, я хочу запустить приведенную ниже команду

`nohup python ./myfile.py &`

и этот файл myfile.py должен даже после выхода моего основного питона script.

Кроме того, я хочу получить pid нового процесса.

Я пробовал методы os.spawnl*, os.exec* и subprocess.Popen, все завершают мой myfile.py, если мой main.py script завершает работу.

Возможно, что-то не хватает.

Обновление. Можно ли использовать os.startfile с xdg-open? Это правильный подход?

Пример

a = subprocess.Popen([sys.executable, "nohup /usr/bin/python25 /long_process.py &"],\
     stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
print a.pid

Если я проверяю ps aux | grep long_process, я не вижу никакого процесса.

long_process.py, который продолжает печатать текст: нет выхода.

Я делаю что-то не так здесь?

4b9b3361

Ответ 1

Вы открываете свой длительный процесс и поддерживаете его. Поэтому вы ожидаете поговорить с ним. Когда вы покинете yor launcher script, вы больше не можете разговаривать с ним. Длительный процесс получает SIGPIPE и выходит.

Следующие только что сработали для меня (Linux, Python 2.7).

Создайте долгосрочный исполняемый файл:

$ echo "sleep 100" > ~/tmp/sleeper.sh

Запустите Python REPL:

$ python
>>>

import subprocess
import os
p = subprocess.Popen(['/bin/sh', os.path.expanduser('~/tmp/sleeper.sh')])
# look ma, no pipes!
print p.pid
# prints 29893

Выйдите из REPL и увидите, что процесс все еще запущен:

>>> ^D
$ ps ax | grep sleeper
29893 pts/0    S      0:00 /bin/sh .../tmp/sleeper.sh
29917 pts/0    S+     0:00 grep --color=auto sleeper

Если вы хотите сначала связаться с запущенным процессом, а затем оставить его в покое для дальнейшего использования, у вас есть несколько вариантов:

  • Обработайте SIGPIPE в своем долговременном процессе, не умрете на нем. Живой без stdin после завершения процесса запуска.
  • Передайте все, что вам нужно, используя аргументы, среду или временный файл.
  • Если вы хотите двунаправленную связь, рассмотрите возможность использования именованного канала (man mkfifo) или сокета или написания надлежащего сервера.
  • Сделайте длинную вилку процесса после начальной фазы двусторонней связи.

Ответ 2

Вы можете использовать os.fork().

import os
pid=os.fork()
if pid==0: # new process
    os.system("nohup python ./myfile.py &")
    exit()
# parent process continues

Ответ 3

  Я не видел ни одного запущенного процесса.

Вы не видите работающего процесса, потому что дочерний процесс python завершается немедленно. Аргументы Popen неверны, как говорит user4815162342 в комментарии.

Чтобы запустить полностью независимый процесс, вы можете использовать python-daemon пакет или использовать systemd/supervisord/etc:

#!/usr/bin/python25
import daemon
from long_process import main

with daemon.DaemonContext():
    main()

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

with open(os.devnull, 'r+b', 0) as DEVNULL:
    p = Popen(['/usr/bin/python25', '/path/to/long_process.py'],
              stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT, close_fds=True)
time.sleep(1) # give it a second to launch
if p.poll(): # the process already finished and it has nonzero exit code
    sys.exit(p.returncode)

Если дочернему процессу не требуется python2.5, вы можете использовать вместо него sys.executable (чтобы использовать ту же версию Python, что и у родительского).

Примечание: код закрывает DEVNULL в родительском элементе, не дожидаясь завершения дочернего процесса (это не влияет на дочерний процесс).