1、项目的需求来源

      做为程序员码代码,开发软件,开发通信协议,相信避免不了与各种校验码打交道。校验码是通信协议中数据接收方用来校验数据合法性的一个编码。那么举个栗子,请看今早我和隔壁老王的对话,

隔壁老王:今天你吃了么?“嘎哈”

        老赵:我今天吃的是包子。“哇哈”

        哎,有人会问了,你和老王说话怎么还带着口头禅,这个就是为了向你说明校验码,老王说话后面的加引号的“嘎哈”,我听到后,知道老王是东北的,说话带个“嘎哈”就验证了这是老王说的,老王听到我说话后面加引号的“哇哈”,知道了这是老赵说话的校验码,这话是老赵说的。

        根据实际的MODBUS RTU通信协议就能更好的理解出来通信协议中校验码的功能:

地址

功能代码

数据数量

数据1

...

数据n

CRC低字节

CRC高字节

这个协议中的最后两个字节,CRC低字节,CRC高字节就是校验码了,这个校验码是前面所有数据、数据数量、功能代码、地址这些字节经过特殊的运算得出来。

      开发过程中今天MODBUS协议,明天ISO14443A,后天TCP/IP协议...,测试过程中要编写各种协议,计算各种校验码,我想你最开始是手算或都上网找一个工具来计算,今天咱们就写一个单机板的计算工具,具有计算异或和,累加和,MODBUS CRC,ISO14443 CRC计算功能的校验码计算工具。先上开发工作成果,哈哈

lua crc校验代码 crc校验码计算程序代码_CRC计算工具

2、各种校验码的计算算法

     (1)NOR 异或和计算

           nor = d1 ^ d2 ^ ... dn   d1 - dn是要参与计算的数据,是一个单字节的数据,这个异或计算就是对所有数据进行逻辑按位异或

     (2)SUM累加和计算

          sum = d1 + d2 + d3...dn     d1 - dn是要参与计算的数据,是一个单字节的数据,这个累加和计算就是对所有数据进行累加,累加的结果还是取单字节,不考虑溢出的高位部分

     (3)ISO14443的CRC计算

           G(x)=x^16 + x ^12 + x^5 + 1,这个算法复杂一点,具体可以参考ISO14443协议中的第60页,ISO14443协议中有CRC A, CRC B的计算法,这个两种校验码的算法一样,初始值不一样。

      (4)MODBUS CRC计算

           这个CRC计算也复杂一点,具体可以参考MODBUS协议的第72页,为了加快计算速度,采用查表的方法来计算CRC值。

3、设计UI界面

         打开QtCreat新建一个UI文件,按照你想的样子添加控件,我的设计是这个样子的。

lua crc校验代码 crc校验码计算程序代码_小程序_02

      窗口分成上下两个输入输出文本框,上面的用于输入要计算的数据,下面的用于输出计算结果,中间有放有单选按钮,用于选择计算的算法,最下面还有两个单选按钮“结果取反”和“结果不取反”这个选项只对计算NOR时有效,对NOR计算的结果增加一次取反操作,其他算法计算时无效。界面编辑完成后,保存,工程目录下面会生成一个mainwindow.ui的文件,在命令行中运行pyuic5 mainwindow.ui -o mainwindow.py,把ui文件生成了py的代码文件。

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

# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.8.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.setEnabled(True)
        MainWindow.resize(472, 349)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(450, 349))
        MainWindow.setMaximumSize(QtCore.QSize(500, 349))
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.centralWidget.sizePolicy().hasHeightForWidth())
        self.centralWidget.setSizePolicy(sizePolicy)
        self.centralWidget.setObjectName("centralWidget")
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(10, 0, 91, 16))
        self.label.setObjectName("label")
        self.textEdit = QtWidgets.QTextEdit(self.centralWidget)
        self.textEdit.setGeometry(QtCore.QRect(10, 20, 441, 101))
        self.textEdit.setObjectName("textEdit")
        self.label_2 = QtWidgets.QLabel(self.centralWidget)
        self.label_2.setGeometry(QtCore.QRect(10, 130, 81, 16))
        self.label_2.setObjectName("label_2")
        self.textEdit_2 = QtWidgets.QTextEdit(self.centralWidget)
        self.textEdit_2.setGeometry(QtCore.QRect(10, 150, 451, 101))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.textEdit_2.sizePolicy().hasHeightForWidth())
        self.textEdit_2.setSizePolicy(sizePolicy)
        self.textEdit_2.setObjectName("textEdit_2")
        self.pushButton = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton.setGeometry(QtCore.QRect(380, 260, 75, 23))
        self.pushButton.setStyleSheet("color: rgb(85, 0, 255);\n"
"font: 75 9pt \"Arial\";")
        self.pushButton.setObjectName("pushButton")
        self.radioButton = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton.setGeometry(QtCore.QRect(10, 260, 89, 16))
        self.radioButton.setChecked(True)
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_2.setGeometry(QtCore.QRect(120, 260, 89, 16))
        self.radioButton_2.setObjectName("radioButton_2")
        self.radioButton_3 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_3.setGeometry(QtCore.QRect(90, 130, 71, 16))
        self.radioButton_3.setObjectName("radioButton_3")
        self.radioButton_4 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_4.setGeometry(QtCore.QRect(160, 130, 71, 16))
        self.radioButton_4.setObjectName("radioButton_4")
        self.radioButton_5 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_5.setGeometry(QtCore.QRect(230, 130, 81, 16))
        self.radioButton_5.setObjectName("radioButton_5")
        self.radioButton_6 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_6.setGeometry(QtCore.QRect(310, 130, 81, 16))
        self.radioButton_6.setObjectName("radioButton_6")
        self.radioButton_7 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_7.setGeometry(QtCore.QRect(390, 130, 89, 16))
        self.radioButton_7.setObjectName("radioButton_7")

        #创建一个buttongroup进行分组
        self.computButtonGroup = QtWidgets.QButtonGroup(self.centralWidget)
        self.computButtonGroup.addButton(self.radioButton_3)
        self.computButtonGroup.addButton(self.radioButton_4)
        self.computButtonGroup.addButton(self.radioButton_5)
        self.computButtonGroup.addButton(self.radioButton_6)
        self.computButtonGroup.addButton(self.radioButton_7)
        self.radioButton_3.setChecked(True)
        
        MainWindow.setCentralWidget(self.centralWidget)
        self.menuBar = QtWidgets.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 472, 23))
        self.menuBar.setObjectName("menuBar")
        self.menu = QtWidgets.QMenu(self.menuBar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menuBar)
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        MainWindow.setStatusBar(self.statusBar)
        self.actionud = QtWidgets.QAction(MainWindow)
        self.actionud.setObjectName("actionud")
        self.actionvec = QtWidgets.QAction(MainWindow)
        self.actionvec.setObjectName("actionvec")
        self.menu.addAction(self.actionud)
        self.menu.addAction(self.actionvec)
        self.menuBar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Nor computer"))
        self.label.setText(_translate("MainWindow", "输入数据(HEX)"))
        self.textEdit.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">请输入十六进制数据,以空格分隔</p></body></html>"))

        #设置默认选中输入框中的文字 zhaoshimin 20180829
        self.textEdit.selectAll()
        self.label_2.setText(_translate("MainWindow", "计算结果(HEX)"))
        self.pushButton.setText(_translate("MainWindow", "计算"))
        self.radioButton.setText(_translate("MainWindow", "结果取反"))
        self.radioButton_2.setText(_translate("MainWindow", "结果不取反"))
        self.radioButton_3.setText(_translate("MainWindow", "NOR计算"))
        self.radioButton_4.setText(_translate("MainWindow", "SUM计算"))
        self.radioButton_5.setText(_translate("MainWindow", "CRC-A计算"))
        self.radioButton_6.setText(_translate("MainWindow", "CRC-B计算"))
        self.radioButton_7.setText(_translate("MainWindow", "ModbusCRC"))
        self.menu.setTitle(_translate("MainWindow", "帮助"))
        self.actionud.setText(_translate("MainWindow", "关于"))
        self.actionvec.setText(_translate("MainWindow", "退出"))

 

 

4、编写各个算法的计算算法

         另外创建一个Nor_com.py的文件,这个文件用于实现计算算法,算法和界面文件分开,减少业务逻辑和界面的耦合性。

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtGui import QIcon
from mainwindow import Ui_MainWindow
import sys
from picon import *

aucCRCHi = [
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40]

aucCRCLo = [
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
    0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
    0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
    0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 
    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
    0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 
    0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
    0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
    0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
    0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
    0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80, 0x40]
#modbus crc计算函数
def  modbus_crc(data):
    CRCHi = 0xFF
    CRCLo = 0xFF
    index = 0

    for i in range(0, len(data)):
        index = CRCLo ^ data[i]
        CRCLo = CRCHi ^ aucCRCHi[index]
        CRCHi = aucCRCLo[index]
        
        

    return ((CRCHi << 8 )| CRCLo)

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

        
        # 设置应用程序的窗口图标
        self.setWindowIcon(QIcon(":/NOR_computer.png"))

        
        #默认选择结果取反
        self.radioButton.setChecked(True)
        self.pushButton.clicked.connect(self.nor_com)
        self.actionud.triggered.connect(self.about)      #菜单的点击事件是triggered
        self.actionvec.triggered.connect(self.close) 
    def about(self):
        print('this is about')
        #弹出关于对话框
        QMessageBox.about(self,("关于"),("""Nor Computer V1.0\nSupport: fhqlongteng@163.com\nCopyright: 1982-2017"""))
        QMessageBox.StandardButtons(QMessageBox.Ok)
    def nor_com(self):
        self.statusBar.showMessage('开始计算')
        #从输入框读入字符串
        input_s = self.textEdit.toPlainText()
        #删除前面和后面的空格
        input_s = input_s.strip()
        out_s = input_s
        nor = 0
        sum = 0
        crc_type = 0x6363
        modbus_data = []
       

        if  self.radioButton_5.isChecked():
            #ISO14443A CRC A的计算初值
            crc_type = 0x6363
        elif self.radioButton_6.isChecked():
            #ISO14443A CRC B的计算初值
            crc_type = 0xFFFF

        
        while input_s !='':
            try:
                num = int(input_s[0:2],16)
            except:
                print(sys.exc_info()[0])
                self.statusBar.showMessage('计算中:ValueError')
                #弹出警告对话框
                QMessageBox.warning(self,("警告"),("""请输入十六进制字节数据,以空格隔开"""))
                QMessageBox.StandardButtons(QMessageBox.Ok)
                return None
            

            #判断进行nor运算还是sum运算
            if self.radioButton_3.isChecked():
                #异或和计算
                nor = nor ^ num
            elif self.radioButton_4.isChecked():
                #SUN累加和运算
                nor = nor + num
            elif self.radioButton_5.isChecked() or self.radioButton_6.isChecked():
                #ISO14443A CRC运算
                sum = num ^ (crc_type & 0xFF)
                sum = (sum ^ (sum << 4)) & 0xFF
                crc_type = (crc_type >> 8) ^ ((sum << 8) & 0xffff) ^ ((sum << 3) & 0xffff) ^ ((sum >> 4) & 0xffff)
                crc_type = crc_type & 0xFFFF
            elif self.radioButton_7.isChecked():
                #把数据放入计算列表中去
                modbus_data.append(num)
                
                
            input_s = input_s[2:]
            input_s = input_s.strip()
            
        
        #NOR SUM的计算结果取反操作
        if self.radioButton.isChecked():
            nor = ~nor
            
        else:
            pass

        
        nor = nor & 0xFF
        #print('%02x'%(nor))

        
        #状态栏显示和输出计算结果
        if self.radioButton_4.isChecked():
            out_s = out_s + ' ' + '{:02x}'.format(nor)
            self.statusBar.showMessage('计算完成    SUM=0x' + '{:x}'.format(nor).upper() + '(' +'{:d}'.format(nor)+')')
        elif self.radioButton_3.isChecked():
            out_s = out_s + ' ' + '{:02x}'.format(nor)
            self.statusBar.showMessage('计算完成    NOR=0x' + '{:x}'.format(nor).upper() + '(' +'{:d}'.format(nor)+')')
            
        elif self.radioButton_5.isChecked():
            #CRC A计算结果
            out_s = out_s + ' ' + '{:02x}'.format(crc_type & 0xFF) + ' ' + '{:02x}'.format(crc_type >> 8)
            self.statusBar.showMessage('计算完成  ISO14443A  CRCA=0x' + '{:x}'.format(crc_type).upper() + '(' +'{:d}'.format(crc_type)+')')
            
        elif self.radioButton_6.isChecked():
            #CRC B计算结果
            crc_type = (~crc_type) & 0xffff
            out_s = out_s + ' ' + '{:02x}'.format(crc_type >> 8) + ' ' + '{:02x}'.format(crc_type & 0xFF)
            self.statusBar.showMessage('计算完成  ISO14443B  CRCB=0x' + '{:x}'.format(crc_type).upper() + '(' +'{:d}'.format(crc_type)+')')    
            
        elif self.radioButton_7.isChecked():
            #MODBUS crc计算结果
            crc = modbus_crc(modbus_data)
            out_s = out_s + ' ' + '{:02x}'.format(crc & 0xFF) + ' ' + '{:02x}'.format((crc >> 8) & 0xFF)
            self.statusBar.showMessage('计算完成  Modbus CRC_L=0x' + '{:02X}'.format(crc & 0xFF).upper() + ' CRC_H=0x' +'{:02X}'.format(crc >> 8))  
        #转换成大写字母输出
           
        self.textEdit_2.setText(out_s.upper())

        

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())

     5、设计软件的图标

     软件的图标设计一个ico类型的文件和png类型的文件,两个图标一样,不同的文件格式而已,命名为Nor_commputer.ico, Nor_commputer.png,ico文件用于打包成EXE程序里的软件图标,png文件用于在程序窗口的左上角显示出来一个图标。 编辑一个资源文件nor_com.qrc,写入软件中要调用的图片资源Nor_commputer.png。最后命令行中输入pyrcc5 nor_com.qrc -o pyico.py生成程序内部显示图标使用的图标文件。

lua crc校验代码 crc校验码计算程序代码_校验码_03

     6、打包生成可执行文件

        使用pyinstaller打包,命令行中输入 pyinstaller --icnotallow=Nor_com.ico --paths=E:\python_test\api-ms-win -F -w Nor_com.py运行,具体使用方法可以参考我的博文python使用pyinstaller打包生成EXE可执行文件。