subprocess.Popen
子进程代码 child.py
import sys
if __name__ == '__main__':
print("stdout 输出", file=sys.stdout) # 模拟info日志
print("stderr 输出", file=sys.stderr) # 模拟错误日志
父进程代码Father.py
import time
import os, traceback
import subprocess
def open_process(script_path, stdout_file, stderr_file):
args = ['python', script_path]
process = subprocess.Popen(
# stdin 表示可以接收输入
args,
stdin=subprocess.PIPE,
stdout=stdout_file,
stderr=stderr_file,
env=os.environ.copy(),
)
i = 1
while True:
code = process.poll()
if code is None:
time.sleep(0.1)
print("[Starter] script_path=%s still running" % script_path)
i = i + 1
continue
elif code == 0:
# out,stderr = process.communicate() 此时stdout和error都没有数据,因为都被重定向到文件中了
print("[Starter] script_path=%s success" % script_path)
break
else:
raise Exception("子进程异常")
def create_dir(path):
directory = os.path.dirname(path)
# 如果目录不存在,则创建它
if not os.path.exists(directory):
os.makedirs(directory)
if __name__ == "__main__":
# 构建子进程的日志文件
stdout_path = os.path.join("./", "logs", "stdout")
stderr_path = os.path.join("./", "logs", "stderr")
# 目录不存在则创建
create_dir(stdout_path)
create_dir(stderr_path)
stdout = open(stdout_path, "a")
stderr = open(stderr_path, "a")
try:
open_process("child.py", stdout, stderr)
except Exception as e:
traceback.print_exc()
finally:
stdout.close() # 关闭文件
stderr.close() # 关闭文件
应用场景
subprocess.Popen() 可以执行shell命令,可以执行python文件,可以执行java jar包。 因此在进程大型框架研发的时候会经常用到, 这样的话其实子进程完全可以避免将日志打印在文件中,直接输出到控制台即可。 日志可用上面的方式由父进程进行收集。