创建子进程:
import subprocess
cmd = 'python3 -u server.py'
server_process = subprocess.Popen(cmd.split(), shell=False, stdout=subprocess.PIPE, cwd=os.getcwd(), start_new_session=True)
# 获取子进程输出,但会阻塞
# for line in iter(server_process.stdout.readline, b''):
# print(line)
参数:
python的-u参数:可让输出不被缓冲,避免出现程序stdout不输出的情况。
shell=True:可轮流执行多个指令,指令之间分号隔开。pyinstaller打包后,shell=True时子进程不会跳出黑框,而shell=False会跳出黑框。
cwd=os.getcwd():子进程以父进程的工作目录为准。
start_new_session=True:子进程与父进程分离,不受父进程影响。
父进程关闭子进程:
方法一:若 subprocess.Popen的shell参数为False时,执行以下指令可关闭子进程:
server_process.kill() # server_process是subprocess.Popen返回的对象
pid, status = os.wait()
注:一定要调用os.wait()以回收资源,否则子进程会变为僵尸进程。
方法二:下述方法等同于shell指令kill -9,linux下可用。
with open(file_path, 'r') as f:
pid = int(f.read())
os.kill(pid, signal.SIGKILL)
方法三:若 subprocess.Popen的shell参数为True时,上述方法无法关闭shell。执行以下指令关闭子进程:
process = psutil.Process(server_process.pid)
for child in process.children(recursive=True):
child.kill()
process.kill()
子进程输出pid:
子进程可输出pid,用于被其他进程控制:
pid = os.getpid()
with open(file_path, 'w') as f:
f.write(str(pid))
父进程可根据pid判断子进程是否存活:
with open(file_path, 'r') as f:
pid = int(f.read())
stat = psutil.pid_exists(pid)
if stat is True:
print('alive')
else:
print('dead')