PYTHON3 之 小工具(PyQt5-Pyinstaller-subprocess-ADB)

一、介绍

1、工具目标:

  1)执行adb devices,shell,root,pull命令;

  2)有图形界面,可以傻瓜式操作

2、方法:

  经过技术可行性分析,可以使用python3,PyQt5,pyinstaller,subprocess.run,adb等技术实现目标

3、原理:使用python3 执行 adb相关命令,用PyQt5制作显示界面

 

二、工具

1、界面

先看看界面,使用的控件:groupBox,pushButton,comboBox,lineEdit,toolButton,label,textBrowser,

使用Qt Desiger布置界面,然后转化成python代码

 

 

2、代码

1)界面py,文件名LOG_TOOL_UI.ui


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'LOG_TOOL_UI.ui'
#
# Created by: PyQt5 UI code generator 5.14.2
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(410, 410)
        MainWindow.setMinimumSize(QtCore.QSize(410, 410))
        MainWindow.setMaximumSize(QtCore.QSize(410, 410))
        MainWindow.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox_setting = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_setting.setGeometry(QtCore.QRect(10, 10, 391, 61))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.groupBox_setting.setFont(font)
        self.groupBox_setting.setObjectName("groupBox_setting")
        self.pushButton_devices = QtWidgets.QPushButton(self.groupBox_setting)
        self.pushButton_devices.setGeometry(QtCore.QRect(20, 20, 75, 30))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.pushButton_devices.setFont(font)
        self.pushButton_devices.setObjectName("pushButton_devices")
        self.pushButton_root = QtWidgets.QPushButton(self.groupBox_setting)
        self.pushButton_root.setGeometry(QtCore.QRect(120, 20, 75, 30))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.pushButton_root.setFont(font)
        self.pushButton_root.setObjectName("pushButton_root")
        self.pushButton_cmd = QtWidgets.QPushButton(self.groupBox_setting)
        self.pushButton_cmd.setGeometry(QtCore.QRect(220, 20, 75, 30))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.pushButton_cmd.setFont(font)
        self.pushButton_cmd.setObjectName("pushButton_cmd")
        self.groupBox_option = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_option.setEnabled(True)
        self.groupBox_option.setGeometry(QtCore.QRect(10, 80, 391, 311))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.groupBox_option.setFont(font)
        self.groupBox_option.setTabletTracking(False)
        self.groupBox_option.setAcceptDrops(False)
        self.groupBox_option.setFlat(False)
        self.groupBox_option.setCheckable(False)
        self.groupBox_option.setObjectName("groupBox_option")
        self.comboBox_option_log = QtWidgets.QComboBox(self.groupBox_option)
        self.comboBox_option_log.setGeometry(QtCore.QRect(20, 20, 171, 25))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.comboBox_option_log.setFont(font)
        self.comboBox_option_log.setMouseTracking(False)
        self.comboBox_option_log.setEditable(False)
        self.comboBox_option_log.setMaxVisibleItems(5)
        self.comboBox_option_log.setObjectName("comboBox_option_log")
        self.comboBox_option_log.addItem("")
        self.comboBox_option_log.addItem("")
        self.comboBox_option_log.addItem("")
        self.comboBox_option_log.addItem("")
        self.comboBox_option_log.addItem("")
        self.lineEdit_folderpath = QtWidgets.QLineEdit(self.groupBox_option)
        self.lineEdit_folderpath.setGeometry(QtCore.QRect(20, 70, 241, 25))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.lineEdit_folderpath.setFont(font)
        self.lineEdit_folderpath.setObjectName("lineEdit_folderpath")
        self.toolButton_filepath = QtWidgets.QToolButton(self.groupBox_option)
        self.toolButton_filepath.setGeometry(QtCore.QRect(260, 70, 41, 25))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.toolButton_filepath.setFont(font)
        self.toolButton_filepath.setObjectName("toolButton_filepath")
        self.pushButton_export = QtWidgets.QPushButton(self.groupBox_option)
        self.pushButton_export.setGeometry(QtCore.QRect(310, 66, 61, 31))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.pushButton_export.setFont(font)
        self.pushButton_export.setObjectName("pushButton_export")
        self.labelFilePath = QtWidgets.QLabel(self.groupBox_option)
        self.labelFilePath.setGeometry(QtCore.QRect(20, 50, 71, 21))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.labelFilePath.setFont(font)
        self.labelFilePath.setObjectName("labelFilePath")
        self.label = QtWidgets.QLabel(self.groupBox_option)
        self.label.setGeometry(QtCore.QRect(20, 100, 61, 31))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.textBrowser_logging = QtWidgets.QTextBrowser(self.groupBox_option)
        self.textBrowser_logging.setGeometry(QtCore.QRect(20, 130, 351, 171))
        font = QtGui.QFont()
        font.setFamily("SimSun")
        font.setPointSize(10)
        self.textBrowser_logging.setFont(font)
        self.textBrowser_logging.setObjectName("textBrowser_logging")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 410, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.comboBox_option_log.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.groupBox_setting.setTitle(_translate("MainWindow", "Setting"))
        self.pushButton_devices.setText(_translate("MainWindow", "devices"))
        self.pushButton_root.setText(_translate("MainWindow", "root"))
        self.pushButton_cmd.setText(_translate("MainWindow", "cmd"))
        self.groupBox_option.setTitle(_translate("MainWindow", "Option"))
        self.comboBox_option_log.setCurrentText(_translate("MainWindow", "tbox_message"))
        self.comboBox_option_log.setItemText(0, _translate("MainWindow", "tbox_message"))
        self.comboBox_option_log.setItemText(1, _translate("MainWindow", "ota_log"))
        self.comboBox_option_log.setItemText(2, _translate("MainWindow", "ota_data"))
        self.comboBox_option_log.setItemText(3, _translate("MainWindow", "ds_logcat"))
        self.comboBox_option_log.setItemText(4, _translate("MainWindow", "xf_logcat"))
        self.toolButton_filepath.setText(_translate("MainWindow", "..."))
        self.pushButton_export.setText(_translate("MainWindow", "export"))
        self.labelFilePath.setText(_translate("MainWindow", "log path:"))
        self.label.setText(_translate("MainWindow", "Logging:"))

        #button
        self.pushButton_devices.clicked.connect(MainWindow.adb_devices)
        self.pushButton_root.clicked.connect(MainWindow.adb_root)
        self.pushButton_cmd.clicked.connect(MainWindow.cmd_windows)
        self.pushButton_export.clicked.connect(MainWindow.export_log)
        self.toolButton_filepath.clicked.connect(MainWindow.set_log_folder_path)

 2)核心!!!,实现adb相关命令,文件名LOG_TOOL.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import threading
import subprocess

from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
from LOG_TOOL_UI import *


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        #log folder path
        temp_path = 'C:/Users/Administrator/Downloads'

        #CMD命令-变量
        global CMD_IVI_OTA_DATA_MKDIR
        global CMD_IVI_OTA_DATA_RM
        global CMD_IVI_OTA_LOG_MKDIR
        global CMD_IVI_OTA_LOG_RM
        global CMD_IVI_TBOX_MESSAGES_MKDIR
        global CMD_IVI_TBOX_MESSAGES_RM
        global CMD_ADB_SHELL_MODE_EXIT
        global CMD_XF_IVI_LOGCAT_TO_PC
        global CMD_DS_IVI_LOGCAT_TO_PC
        global CMD_OTA_DATA_TO_IVI
        global CMD_OTA_DATA_TO_PC
        global CMD_OTA_LOG_TO_IVI
        global CMD_OTA_LOG_TO_PC
        global CMD_TBOX_MESSAGES_TO_IVI
        global CMD_TBOX_MESSAGES0_TO_IVI
        global CMD_TBOX_MESSAGES_TO_PC

        #cmd命令
        #初始化global部分略

        #set log folder
        self.lineEdit_folderpath.setText(temp_path)

    #设置log path
    def set_log_folder_path(self):
        temp_path = self.lineEdit_folderpath.text()
        log_folder_path = QFileDialog.getExistingDirectory(self, directory = temp_path)
        if '' == log_folder_path :
            self.lineEdit_folderpath.setText(temp_path)
        else :
            self.lineEdit_folderpath.setText(log_folder_path)

    #打印日志
    def out_put_write(self, text):
#        self.textBrowserLogging.setText(info)
        cursor = self.textBrowser_logging.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.textBrowser_logging.setTextCursor(cursor)
        self.textBrowser_logging.ensureCursorVisible()

    #adb devices
    def adb_devices(self):
        res_devices = subprocess.run('adb devices',
                                     shell = True,
                                     stdout = subprocess.PIPE,
                                     stderr = subprocess.PIPE,
                                     universal_newlines = True)
        if '' == res_devices.stderr :
            print('\n------设备信息!------\n')
            self.out_put_write('\n------设备信息!------\n')
            print(res_devices.stdout)
            self.out_put_write(res_devices.stdout)
        else :
            print(res_devices.stderr)
            self.out_put_write(res_devices.stderr)
            print('\n------获取设备信息失败!------\n')
            self.out_put_write('\n------获取设备信息失败!------\n')

    #adb root
    def adb_root(self):
        res_root = subprocess.run('adb root',
                                  shell = True,
                                  stdout = subprocess.PIPE,
                                  stderr = subprocess.PIPE,
                                  universal_newlines=True)
        if '' == res_root.stderr :
            print(res_root.stdout)
            self.out_put_write(res_root.stdout)
            print('\n------ROOT成功!------\n')
            self.out_put_write('\n------ROOT成功!------\n')
        else :
            print(res_root.stderr)
            self.out_put_write(res_root.stderr)
            print('\n------ROOT失败!------\n')
            self.out_put_write('\n------ROOT失败!------\n')

    #adb shell
    def cmd_windows(self):
        res_cmd_windows = subprocess.run('start cmd.exe',
                                 shell = True,
                                 stdout = subprocess.PIPE,
                                 stderr = subprocess.PIPE,
                                 universal_newlines=True)
        if '' != res_cmd_windows.stderr :
            print(res_cmd_windows.stderr)
            self.out_put_write(res_cmd_windows.stderr)
            print('\n------cmd打开失败!------\n')
            self.out_put_write('\n------cmd打开失败!------\n')

    #导出ivi log
    def export_ds_ivi_logcat(self):
        print('\n------ivi_logcat开始传输...------\n')
        self.out_put_write('\n------ivi_logcat开始传输...------\n')
#        cmd_export_ds_ivi_logcat = CMD_DS_IVI_LOGCAT_TO_PC
        try:
            res_ds_ivi_logcat = subprocess.Popen(CMD_DS_IVI_LOGCAT_TO_PC,
                                                 shell=True,
                                                 stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE,
                                                 universal_newlines=True)
            while res_ds_ivi_logcat.poll() == None:
                ds_ivi_logcat_info = res_ds_ivi_logcat.stdout.readline()
                self.out_put_write(ds_ivi_logcat_info)
            if res_ds_ivi_logcat.returncode :
                print('\n------ivi_logcat传输失败!------\n')
                self.out_put_write('\n------ivi_logcat传输失败!------\n')
                subprocess.CalledProcessError(res_ds_ivi_logcat.returncode, res_ds_ivi_logcat)
            else :
                print('\n------ivi_logcat传输完成!------\n')
                self.out_put_write('\n------ivi_logcat传输完成!------\n')
        except Exception as e:
            print(e)

    # 导出ivi log
    def export_xf_ivi_logcat(self):
        print('\n------ivi_logcat开始传输...------\n')
        self.out_put_write('\n------ivi_logcat开始传输...------\n')
#        cmd_export_ga_ivi_logcat = CMD_GA_IVI_LOGCAT_TO_PC
        try:
            res_xf_ivi_logcat = subprocess.Popen(CMD_XF_IVI_LOGCAT_TO_PC,
                                                 shell=True,
                                                 stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE,
                                                 universal_newlines=True)
            while res_xf_ivi_logcat.poll() == None:
                ga_ivi_logcat_info = res_xf_ivi_logcat.stdout.readline()
                self.out_put_write(ga_ivi_logcat_info)
            if res_xf_ivi_logcat.returncode :
                print('\n------ivi_logcat传输失败!------\n')
                self.out_put_write('\n------ivi_logcat传输失败!------\n')
                subprocess.CalledProcessError(res_xf_ivi_logcat.returncode, res_xf_ivi_logcat)
            else :
                print('\n------ivi_logcat传输完成!------\n')
                self.out_put_write('\n------ivi_logcat传输完成!------\n')
        except Exception as e:
            print(e)
        '''    
        res_ga_ivi_logcat = subprocess.run(CMD_GA_IVI_LOGCAT_TO_PC,
                                           shell = True,
                                           stdout = subprocess.PIPE,
                                           stderr = subprocess.PIPE,
                                           universal_newlines = True)
        if '' == res_ga_ivi_logcat.stderr :
            print(res_ga_ivi_logcat.stdout)
            self.out_put_write(res_ga_ivi_logcat.stdout)
            print('\n------ivi_logcat传输完成!------\n')
            self.out_put_write('\n------ivi_logcat传输完成!------\n')
        else :
            print(res_ga_ivi_logcat.stderr)
            self.out_put_write(res_ga_ivi_logcat.stderr)
            print('\n------ivi_logcat传输失败!------\n')
            self.out_put_write('\n------ivi_logcat传输失败!------\n')
        '''

    # 导出tbox messages
    def export_tbox_messages(self):
        print('\n------tbox_messages开始传输...------\n')
        self.out_put_write('\n------tbox_messages开始传输...------\n')
        cmd_export_tbox_messages = CMD_IVI_TBOX_MESSAGES_RM + ' & ' + CMD_IVI_TBOX_MESSAGES_MKDIR + ' && ' + \
                                   CMD_TBOX_MESSAGES_TO_IVI + ' && ' + CMD_TBOX_MESSAGES0_TO_IVI + ' && ' + \
                                   CMD_TBOX_MESSAGES_TO_PC + ' && ' + CMD_IVI_TBOX_MESSAGES_RM
        try:
            res_tbox_messages = subprocess.Popen(cmd_export_tbox_messages,
                                                 shell=True,
                                                 stdout=subprocess.PIPE,
                                                 stderr=subprocess.PIPE,
                                                 universal_newlines=True)
            while res_tbox_messages.poll() == None:
                tbox_messages_info = res_tbox_messages.stdout.readline()
                self.out_put_write(tbox_messages_info)
            if res_tbox_messages.returncode :
                print('\n------tbox_messages传输失败!------\n')
                self.out_put_write('\n------tbox_messages传输失败!------\n')
                subprocess.CalledProcessError(res_tbox_messages.returncode, res_tbox_messages)
            else :
                print('\n------tbox_messages传输完成!------\n')
                self.out_put_write('\n------tbox_messages传输完成!------\n')
        except Exception as e:
            print(e)

        '''
        res_tbox_messages = subprocess.run(cmd_export_tbox_messages,
                                          shell = True,
                                          stdout = subprocess.PIPE,
                                          stderr = subprocess.PIPE,
                                          universal_newlines = True)
        if '' == res_tbox_messages.stderr :
            print(res_tbox_messages.stdout)
            self.out_put_write(res_tbox_messages.stdout)
            print('\n------tbox_messages传输完成!------\n')
            self.out_put_write('\n------tbox_messages传输完成!------\n')
        else :
            print(res_tbox_messages.stderr)
            self.out_put_write(res_tbox_messages.stderr)
            print('\n------tbox_messages传输失败!------\n')
            self.out_put_write('\n------tbox_messages传输失败!------\n')
        '''

    # 导出ota log
    def export_ota_log(self):
        print('\n------ota_log开始传输...------\n')
        self.out_put_write('\n------ota_log开始传输...------\n')
        cmd_export_ota_log = CMD_IVI_OTA_LOG_RM + ' & ' + CMD_IVI_OTA_LOG_MKDIR + ' && ' + \
                             CMD_OTA_LOG_TO_IVI + ' && ' + CMD_OTA_LOG_TO_PC + ' && ' + CMD_IVI_OTA_LOG_RM
        try:
            res_ota_log = subprocess.Popen(cmd_export_ota_log,
                                           shell = True,
                                           stdout = subprocess.PIPE,
                                           stderr = subprocess.PIPE,
                                           universal_newlines=True)
            while res_ota_log.poll() == None:
                ota_log_info = res_ota_log.stdout.readline()
                self.out_put_write(ota_log_info)
            if res_ota_log.returncode:
                print('\n------ota_log传输失败!------\n')
                self.out_put_write('\n------ota_log传输失败!------\n')
                subprocess.CalledProcessError(res_ota_log.returncode, res_ota_log)
            else:
                print('\n------ota_log传输成功!------\n')
                self.out_put_write('\n------ota_log传输成功!------\n')
        except Exception as e:
            print(e)

    # 导出ota data
    def export_ota_data(self):
        print('\n------ota_data开始传输...------\n')
        self.out_put_write('\n------ota_data开始传输...------\n')
        cmd_export_ota_data = CMD_IVI_OTA_DATA_RM + ' && ' + CMD_IVI_OTA_DATA_MKDIR + ' && ' + \
                              CMD_OTA_DATA_TO_IVI + ' && ' + CMD_OTA_DATA_TO_PC + ' && ' + CMD_IVI_OTA_DATA_RM
        try:
            res_ota_data = subprocess.Popen(cmd_export_ota_data,
                                            shell = True,
                                            stdout = subprocess.PIPE,
                                            stderr = subprocess.PIPE,
                                            universal_newlines=True)

            while res_ota_data.poll() == None:
                ota_data_info = res_ota_data.stdout.readline()
                self.out_put_write(ota_data_info)
            if res_ota_data.returncode:
                print('\n------ota_data传输失败!------\n')
                self.out_put_write('\n------ota_data传输失败!------\n')
                subprocess.CalledProcessError(res_ota_data.returncode, res_ota_data)
            else:
                print('\n------ota_data传输完成!------\n')
                self.out_put_write('\n------ota_data传输完成!------\n')
        except Exception as e:
            print(e)

    # 导出log
    def export_log(self):
#        temp_path = self.lineEdit_folderpath.text()
        get_log_type = self.comboBox_option_log.currentText()

        if get_log_type == 'ota_log' :
            threading.Thread(target=self.export_ota_log).start()
        elif get_log_type == 'tbox_messages' :
            threading.Thread(target=self.export_tbox_messages).start()
        elif get_log_type == 'ds_logcat' :
            threading.Thread(target=self.export_ds_ivi_logcat).start()
        elif get_log_type == 'xf_logcat' :
            threading.Thread(target=self.export_xf_ivi_logcat).start()
        elif get_log_type == 'ota_data' :
            threading.Thread(target=self.export_ota_data).start()
        else :
            print('\n------传输失败!!!------\n')
            self.out_put_write('\n------传输失败!!!------\n')

if __name__ == '__main__':
#    multiprocessing.freeze_support()
    app = QApplication(sys.argv)
    ToolWindow = MainWindow()
    ToolWindow.show()
    sys.exit(app.exec_())

三、遇到的问题(最重要)
1、PyQt5/PyInstaller安装尽量用pip命令在线安装
2、subprocess执行多个adb命令的方法,使用 && 连接命令
3、pyinstaller最好打包成文件夹(-Dw),不要打包成exe可执行文件(-Fw)
4、threading.Thread().start()解决界面没有响应问题
5、PyQt5控件使用
posted @ 2020-06-23 16:15  张小力  阅读(1101)  评论(0编辑  收藏  举报