I’m working with Python 2.7 on Windows 8/XP.
I have a program A that runs another program B using the following code:
p = Popen(["B"], stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() return
B runs a batch script C. C is a long running script and I want B to exit even though C has not finished. I have done it using the following code (in B):
p = Popen(["C"]) return
When I run B, it works as expected. When I run A however, I expected it to exit when B exits. But A waits until C exits even though B has already exitted. Any ideas on what’s happening and what possible solutions could be?
Unfortunately, the obvious solution of changing A to look like B is not an option.
Here is a functional sample code to illustrate this issue:
https://www.dropbox.com/s/cbplwjpmydogvu2/popen.zip?dl=1
The zip file consists of the following files with the following contents:
A.py
from subprocess import PIPE, Popen
import sys
def log(line):
with open("log.txt", "a") as logfile:
logfile.write(line)
log("rnrnA: I'll wait for Brn")
p = Popen(["C:\Python27\python.exe", "B.py"], stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
log("A: Done.rn")
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 Crn")
p = Popen(["C.bat"])
log("B: Not waiting for C at all. bye!rn")
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"
Any input is much appreciated.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You could provide start_new_session analog for the C subprocess:
#!/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]: Process Creation Flags for CreateProcess()
Method 2
Here is a code snippet adapted from Sebastian’s answer and this answer:
#!/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()
I’ve only tested it personally on Windows.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0