zoukankan      html  css  js  c++  java
  • 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(' ------设备信息!------ ')
    self.out_put_write(' ------设备信息!------ ')
    print(res_devices.stdout)
    self.out_put_write(res_devices.stdout)
    else :
    print(res_devices.stderr)
    self.out_put_write(res_devices.stderr)
    print(' ------获取设备信息失败!------ ')
    self.out_put_write(' ------获取设备信息失败!------ ')

    #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(' ------ROOT成功!------ ')
    self.out_put_write(' ------ROOT成功!------ ')
    else :
    print(res_root.stderr)
    self.out_put_write(res_root.stderr)
    print(' ------ROOT失败!------ ')
    self.out_put_write(' ------ROOT失败!------ ')

    #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(' ------cmd打开失败!------ ')
    self.out_put_write(' ------cmd打开失败!------ ')

    #导出ivi log
    def export_ds_ivi_logcat(self):
    print(' ------ivi_logcat开始传输...------ ')
    self.out_put_write(' ------ivi_logcat开始传输...------ ')
    # 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(' ------ivi_logcat传输失败!------ ')
    self.out_put_write(' ------ivi_logcat传输失败!------ ')
    subprocess.CalledProcessError(res_ds_ivi_logcat.returncode, res_ds_ivi_logcat)
    else :
    print(' ------ivi_logcat传输完成!------ ')
    self.out_put_write(' ------ivi_logcat传输完成!------ ')
    except Exception as e:
    print(e)

    # 导出ivi log
    def export_xf_ivi_logcat(self):
    print(' ------ivi_logcat开始传输...------ ')
    self.out_put_write(' ------ivi_logcat开始传输...------ ')
    # 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(' ------ivi_logcat传输失败!------ ')
    self.out_put_write(' ------ivi_logcat传输失败!------ ')
    subprocess.CalledProcessError(res_xf_ivi_logcat.returncode, res_xf_ivi_logcat)
    else :
    print(' ------ivi_logcat传输完成!------ ')
    self.out_put_write(' ------ivi_logcat传输完成!------ ')
    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(' ------ivi_logcat传输完成!------ ')
    self.out_put_write(' ------ivi_logcat传输完成!------ ')
    else :
    print(res_ga_ivi_logcat.stderr)
    self.out_put_write(res_ga_ivi_logcat.stderr)
    print(' ------ivi_logcat传输失败!------ ')
    self.out_put_write(' ------ivi_logcat传输失败!------ ')
    '''

    # 导出tbox messages
    def export_tbox_messages(self):
    print(' ------tbox_messages开始传输...------ ')
    self.out_put_write(' ------tbox_messages开始传输...------ ')
    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(' ------tbox_messages传输失败!------ ')
    self.out_put_write(' ------tbox_messages传输失败!------ ')
    subprocess.CalledProcessError(res_tbox_messages.returncode, res_tbox_messages)
    else :
    print(' ------tbox_messages传输完成!------ ')
    self.out_put_write(' ------tbox_messages传输完成!------ ')
    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(' ------tbox_messages传输完成!------ ')
    self.out_put_write(' ------tbox_messages传输完成!------ ')
    else :
    print(res_tbox_messages.stderr)
    self.out_put_write(res_tbox_messages.stderr)
    print(' ------tbox_messages传输失败!------ ')
    self.out_put_write(' ------tbox_messages传输失败!------ ')
    '''

    # 导出ota log
    def export_ota_log(self):
    print(' ------ota_log开始传输...------ ')
    self.out_put_write(' ------ota_log开始传输...------ ')
    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(' ------ota_log传输失败!------ ')
    self.out_put_write(' ------ota_log传输失败!------ ')
    subprocess.CalledProcessError(res_ota_log.returncode, res_ota_log)
    else:
    print(' ------ota_log传输成功!------ ')
    self.out_put_write(' ------ota_log传输成功!------ ')
    except Exception as e:
    print(e)

    # 导出ota data
    def export_ota_data(self):
    print(' ------ota_data开始传输...------ ')
    self.out_put_write(' ------ota_data开始传输...------ ')
    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(' ------ota_data传输失败!------ ')
    self.out_put_write(' ------ota_data传输失败!------ ')
    subprocess.CalledProcessError(res_ota_data.returncode, res_ota_data)
    else:
    print(' ------ota_data传输完成!------ ')
    self.out_put_write(' ------ota_data传输完成!------ ')
    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(' ------传输失败!!!------ ')
    self.out_put_write(' ------传输失败!!!------ ')

    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控件使用
  • 相关阅读:
    获取 iPhone 上联系人姓名、电话、邮件的代码
    NSDate常用代码范例
    iphone开发之多线程NSThread和NSInvocationOperation
    iphone 定时提醒
    iphone 程序自动登陆
    搞定大厂算法面试之leetcode精讲11剪枝&回溯
    大厂算法面试之leetcode精讲7.双指针
    大厂算法面试之leetcode精讲8.滑动窗口
    大厂算法面试之leetcode精讲15.链表
    大厂算法面试之leetcode精讲10.递归&分治
  • 原文地址:https://www.cnblogs.com/zinthewind/p/13182688.html
Copyright © 2011-2022 走看看