zoukankan      html  css  js  c++  java
  • 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"EXEModuleReadINI
    eadini.exe"
        rose_abs_path = current_path + "\" + r"EXEModuleRose
    ose.exe"
        usage_abs_path = current_path + "\" + r"EXEModuleCPUUsageCPUUsage.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"EXEModuleReadINI
    eadini.exe"
        rose_abs_path = current_path + "\" + r"EXEModuleRose
    ose.exe"
        usage_abs_path = current_path + "\" + r"EXEModuleCPUUsageCPUUsage.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"EXEModuleReadINI
    eadini.exe"
        rose_abs_path = current_path + "\" + r"EXEModuleRose
    ose.exe"
        usage_abs_path = current_path + "\" + r"EXEModuleCPUUsageCPUUsage.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.

  • 相关阅读:
    Linux中文显示乱码?如何设置centos显示中文
    查看mysql主从配置的状态及修正 slave不启动问题
    【Linux】Linux中的0644 和 0755的权限
    阿里云虚拟主机安装wordpress,提示连接数据库失败的解决方法
    neXtep 安装过程整理
    manjaro 设置开机启动脚本
    manjaro本地安装软件后添加快速启动到开始菜单
    k8s svc 添加 debug 端口
    为什么不建议在 MySQL 中使用 UTF-8?
    redis哨兵主从切换过程解析
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/11939748.html
Copyright © 2011-2022 走看看