web-dev-qa-db-ja.com

完全に独立したプロセスを開始する

python script (main.py)]からプロセスを開始したい、具体的には以下のコマンドを実行したい

`Nohup python ./myfile.py &`

このファイルmyfile.pyは、メインpythonスクリプトが終了した後でも必要です。

さらに、新しいプロセスのpidを取得したいです。

os.spawnl*os.exec*subprocess.Popenメソッドを試しましたが、main.pyスクリプトが終了すると、すべてがmyfile.pyを終了します。

何かが足りないかもしれません。

更新:os.startfilexdg-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これはいくつかのテキストを印刷し続けます:終了しません。

ここで何か間違っていますか?

16
Garfield

実行時間の長いプロセスを開き、パイプを保持します。だからあなたはそれに話をすることを期待しています。 yorランチャースクリプトが終了すると、会話できなくなります。 長時間実行プロセスは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 )またはソケットを使用するか、適切なサーバーを作成することを検討してください。
  • 最初の双方向通信フェーズが完了した後、長時間実行されるプロセスを分岐させます。
13
9000

os.fork()を使用できます。

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

実行中のプロセスを確認できませんでした。

pythonプロセスがすぐに終了するため、実行中のプロセスは表示されません。 ser4815162342がコメントで述べている のように、Popen引数は正しくありません。

完全に独立したプロセスを起動するには、 python-daemon package を使用するか、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を閉じます(子には影響しません)。

6
jfs