Python基础之subprocess
前言
subprocess这个函数很好用,类似于控制台执行,功能很多,今天先介绍subprocess调用exe,并行调用两个或两个以上的exe。
Subprocess调用exe
调用exe有几种方式,这里介绍一下subprocess。
p = subprocess.Popen(“./XXX.exe param1 param2”, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
返回值为p.returncode,exe中打印出来的消息为output= p.communicate()[0]
那么有的程序运行时特别耗资源,容易卡死,所以设置一个超时时间,如果在规定时间内可以分析完毕,返回分析结果,如果超时了,杀死exe,返回默认结果。
def Func(): p = subprocess.Popen("./XXX.exe", stdin=subprocess.PIPE, stdout=subprocess.PIPE) try: p.wait(timeout=SECONDS_TIMEOUT) except Exception as e: print("===== process timeout ======") p.kill() return None
output= p.communicate()[0]
err = p.communicate()[1]
print(output)
print(p.returncode)
Subprocess并行调用两个或两个以上的exe
方法一:多线程
知识点:多线程,路径分离,锁定程序运行路径
以并行调用三个exe为例。
1. readini.exe
功能:读取同级目录testini.ini里面的一个值,等待3秒,写入同级目录test1.ini里面
testini.ini
[TEST] name = Sindy age = 20 sex = girl score = 90
2. rose.exe
功能:画一朵玫瑰花,大概运行8S。
3. Usage.exe
功能:画一个动态折线图,时间20S。
CallEXEParaller.py
#!/usr/bin/env python # _*_ coding: UTF-8 _*_ """================================================= @Project -> File : 20200613 -> CallEXEParaller.py @IDE : PyCharm @Author : zihan @Date : 2020/6/13 14:20 @Desc :目的:可以并行调用两个或者多个EXE =================================================""" import subprocess import sys import os import threading SECONDS_TIMEOUT = 1000 def execute_exe(exe_path, exe_param): folder_path, file_name = os.path.split(exe_path) # os.chdir(folder_path) p = subprocess.Popen(exe_path + " " + exe_param, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=folder_path) try: p.wait(timeout=SECONDS_TIMEOUT) except Exception as e: p.kill() # os.chdir(current_path) print("===== process timeout ======") return None except: s = sys.exc_info() str_error = "Error '%s' happened on line %d" % (s[1], s[2].tb_lineno) p.kill() # os.chdir(current_path) return None # os.chdir(current_path) output = p.communicate()[0] err = p.communicate()[1] print(output) print(p.returncode) if __name__ == '__main__': current_path = os.getcwd() readini_abs_path = current_path + "\\" + r"EXEModule\ReadINI\readini.exe" rose_abs_path = current_path + "\\" + r"EXEModule\Rose\rose.exe" usage_abs_path = current_path + "\\" + r"EXEModule\CPUUsage\CPUUsage.exe" t1 = threading.Thread(target=execute_exe, args=(readini_abs_path, "")) t2 = threading.Thread(target=execute_exe, args=(rose_abs_path, "")) t3 = threading.Thread(target=execute_exe, args=(usage_abs_path, "")) t1.start() t2.start() t3.start()
注意subprocess的cwd参数,它可以指定当前exe运行在哪个路径下。程序中执行的就是如果调用哪个exe,那么就在exe所在的目录下执行程序。
方法二:多进程
在用多线程运行时发现了一个问题,如果在exe运行完后要作出相应的操作,那么必须得耗时最长的程序运行完后,在一起打印消息。这是因为p.communicate()[0]在阻塞的原因。解决此问题的方法就是用多线程进行调用。
CallEXEParallel.py
#!/usr/bin/env python # _*_ coding: UTF-8 _*_ """================================================= @Project -> File : 20200613 -> CallEXEParaller.py @IDE : PyCharm @Author : zihan @Date : 2020/6/13 14:20 @Desc :目的:可以并行调用两个或者多个EXE 方法一:多进程方法调用,完美实现 方法二:多线程调用,因为有p.communicate()[0]的存在,会导致打印阻塞,一直等到耗时长的程序执行完才会打印消息 =================================================""" import subprocess import sys import os import threading import multiprocessing def execute_exe(exe_path, exe_param): print("aaa") folder_path, file_name = os.path.split(exe_path) try: p = subprocess.Popen(exe_path + " " + exe_param, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=folder_path) except: s = sys.exc_info() str_error = "Error '%s' happened on line %d" % (s[1], s[2].tb_lineno) print(str_error) return None output = p.communicate()[0] err = p.communicate()[1] print(output) print(p.returncode) if p.returncode == 0: print("pass") else: print("fail") # 方法一:多进程方法调用 def multiprocess_test(): current_path = os.getcwd() readini_abs_path = current_path + "\\" + r"EXEModule\ReadINI\readini.exe" rose_abs_path = current_path + "\\" + r"EXEModule\Rose\rose.exe" usage_abs_path = current_path + "\\" + r"EXEModule\CPUUsage\CPUUsage.exe" p1 = multiprocessing.Process(target=execute_exe, args=(readini_abs_path, "")) p1.start() p2 = multiprocessing.Process(target=execute_exe, args=(rose_abs_path, "")) p2.start() p3 = multiprocessing.Process(target=execute_exe, args=(usage_abs_path, "")) p3.start() p1.join() p2.join() p3.join() # 方法二:多线程方法调用 def threading_test(): current_path = os.getcwd() readini_abs_path = current_path + "\\" + r"EXEModule\ReadINI\readini.exe" rose_abs_path = current_path + "\\" + r"EXEModule\Rose\rose.exe" usage_abs_path = current_path + "\\" + r"EXEModule\CPUUsage\CPUUsage.exe" t1 = threading.Thread(target=execute_exe, args=(readini_abs_path, "")) t2 = threading.Thread(target=execute_exe, args=(rose_abs_path, "")) t3 = threading.Thread(target=execute_exe, args=(usage_abs_path, "")) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() if __name__ == '__main__': # threading_test() multiprocess_test()
OK.