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
View Code

 

 

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()
View Code

 

注意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()
View Code

 

OK.

 

posted @ 2019-11-27 09:07  o云淡风轻o  阅读(2478)  评论(0编辑  收藏  举报