21

Windows 8/XP で Python 2.7 を使用しています。

次のコードを使用して別のプログラム B を実行するプログラム A があります。

p = Popen(["B"], stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
return

B はバッチ スクリプト C を実行します。C は長時間実行されるスクリプトであり、C が終了していなくても B を終了させたいと考えています。次のコード(B)を使用して実行しました:

p = Popen(["C"])
return

B を実行すると、期待どおりに動作します。ただし、A を実行すると、B が終了すると終了すると予想されました。しかし、B が既に終了していても、A は C が終了するまで待機します。何が起こっているのか、どのような解決策が考えられるのかについてのアイデアはありますか?

残念ながら、A を B のように変更するという明白な解決策は、オプションではありません。

この問題を説明するための機能サンプル コードを次に示します: https://www.dropbox.com/s/cbplwjpmydogvu2/popen.zip?dl=1

zip ファイルは、次の内容の次のファイルで構成されます。

A.py

from subprocess import PIPE, Popen
import sys

def log(line):
    with open("log.txt", "a") as logfile:
        logfile.write(line)

log("\r\n\r\nA: I'll wait for B\r\n")

p = Popen(["C:\\Python27\\python.exe", "B.py"], stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()

log("A: Done.\r\n")
sys.exit(0)

B.py

from subprocess import Popen, PIPE
import sys

def log(line):
    with open("log.txt", "a") as logfile:
        logfile.write(line)

log("B: launching C\r\n")

p = Popen(["C.bat"])

log("B: Not waiting for C at all. bye!\r\n")
sys.exit(0)

C.bat

@echo off
echo C: Start long running task : %time% >>  "log.txt"
ping -n 10 127.0.0.1>nul
echo C: Stop long running task : %time% >>  "log.txt"

どんな入力でも大歓迎です。

4

2 に答える 2

27

サブプロセスstart_new_sessionにアナログを提供できます。C

#!/usr/bin/env python
import os
import sys
import platform
from subprocess import Popen, PIPE

# set system/version dependent "start_new_session" analogs
kwargs = {}
if platform.system() == 'Windows':
    # from msdn [1]
    CREATE_NEW_PROCESS_GROUP = 0x00000200  # note: could get it from subprocess
    DETACHED_PROCESS = 0x00000008          # 0x8 | 0x200 == 0x208
    kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)  
elif sys.version_info < (3, 2):  # assume posix
    kwargs.update(preexec_fn=os.setsid)
else:  # Python 3.2+ and Unix
    kwargs.update(start_new_session=True)

p = Popen(["C"], stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)
assert not p.poll()

[1]: CreateProcess() のプロセス作成フラグ

于 2012-11-06T18:17:02.497 に答える
0

これは、セバスチャンの回答とこの回答から改作されたコードスニペットです。

#!/usr/bin/env python
import os
import sys
import platform
from subprocess import Popen, PIPE

# set system/version dependent "start_new_session" analogs
kwargs = {}
if platform.system() == 'Windows':
    # from msdn [1]
    CREATE_NEW_PROCESS_GROUP = 0x00000200  # note: could get it from subprocess
    DETACHED_PROCESS = 0x00000008          # 0x8 | 0x200 == 0x208
    kwargs.update(creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, close_fds=True)  
elif sys.version_info < (3, 2):  # assume posix
    kwargs.update(preexec_fn=os.setsid)
else:  # Python 3.2+ and Unix
    kwargs.update(start_new_session=True)

p = Popen(["C"], stdin=PIPE, stdout=PIPE, stderr=PIPE, **kwargs)
assert not p.poll()

私はWindowsでのみ個人的にテストしました。

于 2017-02-28T03:30:17.983 に答える