用wxpython实现一个简单的命令行执行小工具

  1. 工具开发缘由:
    由于在工作中经常会遇到需要给设备下发指令来进行操作,并且大部门指令都是固定的,并且有些还特别长,不易记住,经常通过复制&粘贴去下发效率不高,很繁琐,因此想做一个简单的小工具,可以直接通过点击按键的方式下发指令。当然有的人可能觉得用bat脚本不也可以嘛,当然也是可以的,但是如果命令行多了,每次执行的命令行顺序不固定,那是不是需要写很多个.bat脚本呢?当然这个就各求所需了哈。

  2. 下面介绍一下工具实现的界面是怎样的。
    a.一个简单的输出框,用于输出命令行执行的回显
    b.所有命令行都通过点击按钮下发
    c.界面大致如下(很简洁)
    在这里插入图片描述

  3. UI需求:
    a.每个按钮都可以自定义名称和指令
    b.按键数量可以根据指令数量自动生成(例:我只有3个指令则只生成3个按钮)
    c.回显内容的字体用颜色区分,便于快速识别。(下发的指令回显用黑色字体,执行返回结果用蓝色字体,报错的结果用红色字体)
    d.按键为每行显示2个(如果命令行比较多的话也可以显示多个,可自行修改代码)

  4. 实现思路
    a.UI界面可以通过wxpython来做
    b.命令行指令的下发可以通过subprocess来实现
    c.按键名称和指令可以通过json文档来获取,key为按键名,value为指令,注:JSON文件名为command.json
    d.按键数量通过循环自动生成,json中有多少key则生成多少按键。
    e.json文件应与执行代码放在同一文件夹下,若没有json文档,首先会提示报错,然后会自动生成一份初始化json文件。
    json文件样式:
    在这里插入图片描述
    5.代码:

# -- encoding:utf-8 --

import sys
import subprocess
import wx
import json
import os


class MyFrame(wx.Frame):
    def __init__(self, parent, id, title, pos, size):
        self.keys = []      # 用于存储json文件中的key的值,即命令行名称
        self.names = []     # 用于存储json文件中的key的值,即命令行名称(因为后面会使用keys,但是keys的结果被改变,因此再另创建一个列表保持命令行名称)
        wx.Frame.__init__(self, parent, id, title, pos, size)
        # 获取json文本中的信息,并转换为JSON格式
        self.panel = wx.Panel(self)    # 创建一个panel
        self.setting_panel()

    # 初始化的数据,如果没有json文件,则会重新创建一个。
    def creat_init(self):
        data = {
            'name1': 'command1',
            'name2': 'command2',
            'name3': 'command3',
            'name4': 'command4'
        }
        read_me = '''
1.将command_tool.exe工具与command.json放在同一文件夹中(同一路径下)
2.command.json文件里面的数据必须以{“key”:"value"}的形式存储,其中必须为英文大括号,英文双引号以及英文冒号。
3.key的值可自定义,为按键名称,value的值为命令行
4.该工具建议最多设置18个命令行(左侧显示的Button数量),如果设置多了,可能无法完整显示后面的button,如果显示屏够大,可以尝试拉大工具窗口试试。
5.Button名字建议别太长,否则界面会不美观
'''
        with open('command.json', 'a') as file:
            file.write(json.dumps(data, indent=2))
        # 如果没有readme.txt指导文件,也新创建一个指导文件
        if not os.path.exists('ReadMe.text'):
            with open('ReadMe.txt', 'a', encoding='utf-8') as file:
                file.write(read_me)

    # 创建UI并实现相关功能
    def setting_panel(self):
        border_h = 10   # 横向间隔
        border_v = 15   # 纵向间隔
        h_all = []      # 存储按键行数的列表,例如第一行的变量为h_all_0,第二行为h_all_1.注:每行两个button
        self.variable = self.keys   # 将button的变量名variable设置为keys的值(此变量名的值可以随便取,但是在for循环中要不断变化)
        title = self.keys
        # 标题
        self.title = wx.StaticText(self.panel, id=-1, label="命令行调试工具", pos=(140, 50))
        # 文本输出框 (pos是输出框位置,size是大小,可自行修改)
        self.output_box = wx.TextCtrl(self.panel, pos=(330, 55), size=(720, 510), style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH|wx.EXPAND)
        # 从command.json文件中读取命令行信息
        try:
            with open('command.json', 'r') as file:
                file_data = file.read()
            self.json_data = json.loads(file_data)
            for json_key in self.json_data:
                self.keys.append(json_key)      # 将key值放入self.keys列表中以备后用
                self.names.append(json_key)     # 将key值放入self.names列表中以备后用
        except:
            self.output_box.SetDefaultStyle(wx.TextAttr(wx.RED))  # 将输出文字颜色变红
            if not os.path.exists('command.json'):
                self.output_box.AppendText('ERROR!!没有找到command.json文件!!\n已为您重新创建command.json文件,请阅读ReadMe指南进行操作!\n或将command.json文件与工具放在同一文件夹目录下!')
                self.creat_init()
            else:
                self.output_box.AppendText("ERROR!未知错误!\n请检查command.json文件格式是否正确!")
            self.output_box.SetDefaultStyle(wx.TextAttr(wx.NullColour))  # 将输出文字颜色变为默认黑色

        # 创建Button,有多少条命令行则创建多少个Button,将Button名设置为json数据的key值(即命令行名称)
        for i in range(len(self.keys)):
            self.variable[i] = wx.Button(self.panel, label=title[i])    # 创建一个button
            self.variable[i].Bind(wx.EVT_BUTTON, lambda evt, type=self.names[i]: self.command_exe(type))    # 按键事件,调用command_exe方法实现
        # 获取一共有多少行按钮(每行两个按钮),如果按钮个数是偶数,则为按钮数除以2的商,如果按钮数为奇数,则行数为按钮数除以2加1
        for i in range(len(self.keys) // 2):
            h_all.append("h_all_" + str(i))
        if len(self.keys) % 2 !=0:
            h_all.append("h_all_" + str(len(self.keys)//2+1))

        # 界面排版,每两个按钮一行
        # 标题(横向位置显示)
        h_title = wx.BoxSizer(wx.HORIZONTAL)
        h_title.Add(self.title, proportion=0, flag=wx.MINIMIZE, border=20)
        # Button(横向位置显示)
        for i in range(len(h_all)):
            h_all[i] = wx.BoxSizer(wx.HORIZONTAL)
            h_all[i].Add(self.variable[i*2], proportion=0, flag=wx.LEFT | wx.RIGHT, border=border_h)
            try:
                h_all[i].Add(self.variable[i*2+1], proportion=0, flag=wx.LEFT | wx.RIGHT, border=border_h)
            except:
                pass
        # 标题的纵向显示
        v_all = wx.BoxSizer(wx.VERTICAL)
        v_all.Add(h_title, proportion = 0, flag=wx.BOTTOM|wx.LEFT|wx.ALIGN_CENTER|wx.RIGHT|wx.TOP, border=15)
        # 所有按键的纵向显示
        for i in range(len(h_all)):
            v_all.Add(h_all[i], proportion=0, flag=wx.BOTTOM | wx.LEFT | wx.TOP, border=border_v)
        self.panel.SetSizer(v_all)

    # 命令执行方法
    def command_exe(self, type):
        if type in self.names:
            self.output_box.AppendText('--' * 20 + '  ' + type + '  ' + '--' * 20 + '\n')
            try:
                result = subprocess.Popen(self.json_data[type], stdout=subprocess.PIPE, shell=True)
                self.output_box.AppendText(self.json_data[type] + '\n')
                self.output_box.SetDefaultStyle(wx.TextAttr(wx.BLUE))   # 将后面输出字段设置为蓝色
                self.output_box.AppendText(result.stdout.read().decode('gbk', "ignore"))
                self.output_box.SetDefaultStyle(wx.TextAttr(wx.NullColour))  # 将后面输出字段设置为默认颜色(黑色)
            except:
                self.output_box.SetDefaultStyle(wx.TextAttr(wx.RED))    # 将后面输出字段设置为红色
                self.output_box.AppendText('ERROR! ' + type + ' failed!' + '\n')
                self.output_box.SetDefaultStyle(wx.TextAttr(wx.NullColour))  # 将后面输出字段设置为默认颜色(黑色)
        else:
            print('ERROR!!')


if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame(parent=None, id=-1, title="命令行调试工具_v0.1", pos=(50, 30), size=(1100, 650))   # 可通过修改size值来自行修改窗口大小
    frame.Show()
    app.MainLoop()

6.总结:
工具实现不难,算上注释和空行才100多行代码,为了便于他人读懂特地加了很多注释。
功能的核心就是subprocess模块的运用,wxpython只是创建一个UI界面,然后便于灵活显示和执行,我们用json文件存储命令行,然后通过读取json存储的数据,来获取按键名和命令行。灵活显示则通过一个简单的for循环来实现。是不是so easy?
这样我们就可以把常用的命令行写入command.json文件中,然后想执行那个直接点击就可以了。后面如果有其他需求也可以自行完善。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值