|
打包Python3.4+PyQt5+Matplotlib程序,使用的py2exe打包,打包生成exe文件,运行出错,生成mymain1.log文件。
错误信息- Traceback (most recent call last):
- File "mymain1.py", line 9, in <module>
- File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
- File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
- File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
- File "<frozen importlib._bootstrap>", line 1161, in _load_backward_compatible
- File "C:\Python34\lib\site-packages\zipextimporter.py", line 86, in load_module
- return zipimport.zipimporter.load_module(self, fullname)
- File "C:\Python34\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 30, in <module>
- _decref = ctypes.pythonapi.Py_DecRef
- File "C:\Python34\lib\ctypes\__init__.py", line 364, in __getattr__
- func = self.__getitem__(name)
- File "C:\Python34\lib\ctypes\__init__.py", line 369, in __getitem__
- func = self._FuncPtr((name_or_ordinal, self))
- AttributeError: function 'Py_DecRef' not found
复制代码 打包setup.py文件
代码如下
- from distutils.core import setup
- import py2exe
- import sys
- # this allows to run it with a simple double click.
- sys.argv.append('py2exe')
- py2exe_options = {
- "includes": ["sip"], # 如果打包文件中有PyQt代码,则这句为必须添加的
- "dll_excludes": ["MSVCP90.dll", ], # 这句必须有,不然打包后的程序运行时会报找不到MSVCP90.dll,如果打包过程中找不到这个文件,请安装相应的库
- "compressed": 1,
- "optimize": 2,
- "ascii": 0,
- "bundle_files": 1, # 关于这个参数请看第三部分中的问题(2)
- }
- setup(
- name='PyQt Demo',
- version='1.0',
- windows=['mymain1.py', ], # 括号中更改为你要打包的代码文件名
- data_files=[("",
- [r"C:\Python34\Lib\site-packages\PyQt5\libEGL.dll"]),
- ("platforms",
- [r"C:\Python34\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll"])],
- zipfile=None,
- options={'py2exe': py2exe_options}
- )
复制代码 用这个文件打包只有Python3.4+PyQt5的程序,没有问题
看错误信息 在ctypes库里没找到Py_DecRef这个函数
以下是要打包的代码- # -*- coding: utf-8 -*-
- import sys
- import time
- import minimalmodbus
- from PyQt5 import QtCore, QtWidgets, QtGui
- import matplotlib
- matplotlib.use("Qt5Agg")
- from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
- from matplotlib.figure import Figure
- from numpy import arange, sin, pi
- class MyMplCanvas(FigureCanvas):
- """这是一个窗口部件,即QWidget(当然也是FigureCanvasAgg)"""
- def __init__(self, parent=None, width=5, height=4, dpi=100):
- fig = Figure(figsize=(width, height), dpi=dpi)
- self.axes1 = fig.add_axes([0.15, 0.55, 0.8, 0.4])
- self.axes2 = fig.add_axes([0.15, 0.1, 0.8, 0.4])
- # 每次plot()调用的时候,我们希望原来的坐标轴被清除(所以False)
- self.axes1.hold(False)
- self.axes2.hold(False)
- self.compute_initial_figure()
- #
- #super(MyMplCanvas, self).__init__(self, fig)
- FigureCanvas.__init__(self, fig)
- self.setParent(parent)
- FigureCanvas.setSizePolicy(self,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Expanding)
- FigureCanvas.updateGeometry(self)
- def compute_initial_figure(self):
- pass
- class MyStaticMplCanvas(MyMplCanvas):
- """静态画布:一条正弦线"""
- def compute_initial_figure(self):
- t = arange(0.0, 3.0, 0.01)
- s = sin(2*pi*t)
- self.axes1.plot(t, s)
- class MyDynamicMplCanvas(MyMplCanvas):
- """动态画布:每秒自动更新,更换一条折线。"""
- x = []
- y1 = []
- y2 = []
- def __init__(self, *args, **kwargs):
- MyMplCanvas.__init__(self, *args, **kwargs)
- timer = QtCore.QTimer(self)
- timer.timeout.connect(self.update_figure)
- timer.start(1000)
- def compute_initial_figure(self):
- if len(self.x) == len(self.y1) and len(self.x) == len(self.y2):
- self.axes1.plot(self.x, self.y1, color="red", linewidth=2)
- self.axes2.plot(self.x, self.y2, "b--", label=r"瞬时流量")
- self.axes2.set_xlabel("time")
- self.axes1.set_ylabel("Volt")
- self.axes1.set_title("PyPlot First Example")
- self.axes1.set_xticks([])
- #self.axes1.set_ylim(-1.2, 1.2)
- #self.axes1.legend()
- def update_figure(self):
- if len(self.x) == len(self.y1) and len(self.x) == len(self.y2):
- self.axes1.plot(self.x,self.y1,label=r"Instantaneous flow rate",color="red",linewidth=2)
- self.axes2.plot(self.x,self.y2, "b--", label=r"Cumulative flow")
- self.axes2.set_xlabel("time")
- self.axes1.set_ylabel("Instantaneous flow rate")
- self.axes2.set_ylabel("Cumulative flow")
- self.axes1.set_title("Record of Flow rate")
- self.axes1.set_xticks([])
- #self.axes1.set_ylim(-1.2, 1.2)
- #self.axes1.legend()
- self.draw()
- class Myalert(QtWidgets.QWidget):
- def __init__(self):
- super(Myalert,self).__init__()
- class errorDialog(QtWidgets.QDialog):
- def __init__(self):
- super(errorDialog, self).__init__()
- self.resize(451, 250)
- self.setSizeGripEnabled(True)
- self.setModal(True)
- icon = QtGui.QIcon()
- icon.addPixmap(QtGui.QPixmap("cross-octagon.png"),
- QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.setWindowIcon(icon)
- #以下三句设置网格放置Widget 位于底部
- self.layoutWidget = QtWidgets.QWidget(self)
- self.layoutWidget.setGeometry(QtCore.QRect(20, 190, 411, 33))
- self.layoutWidget.setObjectName("layoutWidget")
- #以下四句设置底部水平网格HBoxLayout
- self.hboxlayout = QtWidgets.QHBoxLayout(self.layoutWidget)
- self.hboxlayout.setContentsMargins(0, 0, 0, 0)
- self.hboxlayout.setSpacing(6)
- self.hboxlayout.setObjectName("hboxlayout")
- #以下两句设置okButton前的空格
- spacerItem = QtWidgets.QSpacerItem(71, 30,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Minimum)
- self.hboxlayout.addItem(spacerItem)
- #以下三句设置okButton
- self.okButton = QtWidgets.QPushButton(self.layoutWidget)
- self.okButton.setObjectName("okButton")
- self.hboxlayout.addWidget(self.okButton)
- # 以下三句设置cancelButton
- self.cancelButton = QtWidgets.QPushButton(self.layoutWidget)
- self.cancelButton.setObjectName("cancelButton")
- self.hboxlayout.addWidget(self.cancelButton)
- # 以下两句设置cancelButton后的空格
- spacerItem1 = QtWidgets.QSpacerItem(40, 20,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Minimum)
- self.hboxlayout.addItem(spacerItem1)
- # 以下三句设置groupBox,用于放置绘制的TEXT
- self.groupBox = QtWidgets.QGroupBox(self)
- self.groupBox.setGeometry(QtCore.QRect(20, 10, 410, 170))
- self.groupBox.setTitle("")
- self.groupBox.setObjectName("groupBox")
- # 以下三句设置groupBox,用于放置绘制的TEXT
- self.label = QtWidgets.QLabel(self.groupBox)
- self.setlabel(self.label)
- self.label.setGeometry(QtCore.QRect(230, 10, 171, 131))
- self.label.setObjectName("label")
- self.label_2 = QtWidgets.QLabel(self.groupBox)
- self.setlabel(self.label_2)
- self.label_2.setGeometry(QtCore.QRect(10, 10, 221, 41))
- self.label_2.setObjectName("label_2")
- self.label_3 = QtWidgets.QLabel(self.groupBox)
- self.label_3.setGeometry(QtCore.QRect(50, 50, 131, 111))
- self.label_3.setText("")
- self.label_3.setPixmap(QtGui.QPixmap("error"))
- self.label_3.setObjectName("label_3")
- # 下面一句调用retranslateUi()设置部件的文字
- self.retranslateUi(self)
- # 以下三句设置事件触发
- self.okButton.clicked.connect(self.accept)
- self.cancelButton.clicked.connect(self.reject)
- QtCore.QMetaObject.connectSlotsByName(self)
- def setlabel(self,label):
- sizePolicy = QtWidgets.QSizePolicy(
- QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
- sizePolicy.setHorizontalStretch(100)
- sizePolicy.setVerticalStretch(100)
- sizePolicy.setHeightForWidth(label.sizePolicy().hasHeightForWidth())
- font = QtGui.QFont()
- font.setFamily("宋体")
- font.setPointSize(14)
- font.setBold(True)
- font.setWeight(75)
- label.setFont(font)
- pe = QtGui.QPalette()
- pe.setColor(QtGui.QPalette.WindowText, QtCore.Qt.red)
- label.setPalette(pe)
- def retranslateUi(self, Dialog):
- _translate = QtCore.QCoreApplication.translate
- self.setWindowTitle(_translate("Dialog", "ERROR!"))
- self.okButton.setText(_translate("Dialog", "&OK"))
- self.cancelButton.setText(_translate("Dialog", "&Cancel"))
- self.groupBox.setTitle(_translate("Dialog", ""))
- self.text = '串口设置错误!'
- self.label.setText(_translate("Dialog",
- "<html><head/><body><p><span style=" font-size:11pt;">"
- "1、串口是否连接正确</span></p><p><span style=" "
- "font-size:11pt;">"
- "2、串口号设置是否正确</span></p><p><span style=" "
- "font-size:11pt;">"
- "3、波特率是否设置正确</span></p><p><span style=" "
- "font-size:11pt;">"
- "4、设备地址是否正确</span></p></body></html>"))
- self.label_2.setText(_translate("Dialog", "串口连接错误!请检查:"))
- class ApplicationWindow(QtWidgets.QMainWindow):
- def __init__(self):
- QtWidgets.QMainWindow.__init__(self)
- self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
- self.setWindowTitle("程序主窗口")
- self.resize(650, 700)
- self.mysetwidgets()
- def mysetfont(self,fontnum):
- if fontnum == 1:
- font = QtGui.QFont("微软雅黑 Light",14)
- font.setFamily("微软雅黑 Light")
- font.setPointSize(14)
- font.setBold(True)
- font.setWeight(75)
- elif fontnum == 2:
- font = QtGui.QFont()
- font.setFamily("微软雅黑 Light")
- font.setPointSize(12)
- font.setBold(True)
- font.setWeight(75)
- return font
- def mySetsizePolicy(self,sizenum):
- if sizenum == 1:
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
- QtWidgets.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(80)
- sizePolicy.setVerticalStretch(0)
- elif sizenum == 2:
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum,
- QtWidgets.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(50)
- sizePolicy.setVerticalStretch(0)
- elif sizenum == 3:
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
- QtWidgets.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(100)
- sizePolicy.setVerticalStretch(100)
- sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
- elif sizenum == 4:
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(100)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
- return sizePolicy
- def mySetlabel(self,label,fontmun,textformat,alignment,name):
- label.setFont(self.mysetfont(fontmun))
- label.setTextFormat(textformat)
- label.setAlignment(alignment)
- label.setObjectName(name)
- def mySetLCD(self,LCD):
- LCD.setDigitCount(16)
- LCD.setObjectName("lcd")
- LCD.setSegmentStyle(QtWidgets.QLCDNumber.Flat)
- def mysetwidgets(self):
- ''''''
- #以下设置主面板
- self.main_widget = QtWidgets.QWidget(self)
- self.main_widget.setSizePolicy(self.mySetsizePolicy(1))
- self.main_widget.setGeometry(QtCore.QRect(10, 10, 600, 600))
- self.main_widget.setObjectName("main_widget")
- #以下设置网格
- self.gridLayout = QtWidgets.QGridLayout(self.main_widget)
- self.gridLayout.setObjectName("gridLayout")
- #以下设置标签
- self.mylabel = [QtWidgets.QLabel('温度℃',self.main_widget),
- QtWidgets.QLabel('压力KPa', self.main_widget),
- QtWidgets.QLabel('瞬时流量kg/min', self.main_widget),
- QtWidgets.QLabel('累计流量kg', self.main_widget),
- QtWidgets.QLabel('第一路', self.main_widget),
- QtWidgets.QLabel('第二路', self.main_widget)]
- for i in range(6):
- self.mySetlabel(self.mylabel[i],1,
- QtCore.Qt.RichText,QtCore.Qt.AlignCenter,
- "mylabel_1")
- if i==4:
- self.mylabel[i].setSizePolicy(self.mySetsizePolicy(2))
- self.gridLayout.addWidget(self.mylabel[i], 1, 0, 1, 1)
- elif i ==5:
- self.mylabel[i].setSizePolicy(self.mySetsizePolicy(2))
- self.gridLayout.addWidget(self.mylabel[i], 2, 0, 1, 1)
- else:
- self.gridLayout.addWidget(self.mylabel[i], 0, i+1, 1, 1)
- #以下设置LCD
- #创建myLCD数组对应关系如下:
- # myLCD[0] ---------第一路温度单位℃
- # myLCD[1] ---------第一路压力单位KPa
- # myLCD[2] ---------第一路瞬时流量单位kg/min
- # myLCD[3] ---------第一路累计流量单位kg
- # myLCD[4] ---------第二路温度单位℃
- # myLCD[5] ---------第二路压力单位KPa
- # myLCD[6] ---------第二路瞬时流量单位kg/min
- # myLCD[7] ---------第二路累计流量单位kg
- self.myLCD = [QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),
- QtWidgets.QLCDNumber(self.main_widget),]
- for i in range(8):
- self.mySetLCD(self.myLCD[i])
- if i<=3:
- self.gridLayout.addWidget(self.myLCD[i], 1, i + 1, 1, 1)
- else:
- self.gridLayout.addWidget(self.myLCD[i], 2, i - 3, 1, 1)
- #添加动态图
- _translate = QtCore.QCoreApplication.translate
- self.groupBox = QtWidgets.QGroupBox(self.main_widget)
- self.groupBox.setSizePolicy(self.mySetsizePolicy(3))
- self.groupBox.setSizeIncrement(QtCore.QSize(35, 56))
- self.groupBox.setBaseSize(QtCore.QSize(430, 500))
- self.groupBox.setFont(self.mysetfont(2))
- self.groupBox.setTitle(_translate("Dialog", "流量记录"))
- self.groupBox.setObjectName("groupBox")
- self.gridLayout.addWidget(self.groupBox, 3, 0, 1, 5)
- self.myFigure = MyDynamicMplCanvas(self.groupBox, width=5, height=3, dpi=100)
- self.myFigure.setGeometry(QtCore.QRect(10, 20, 700, 520))
- #以下设置报警及按钮
- #在hLayoutWidget上创建水平布局,安放报警提示和按钮
- self.hLayoutWidget = QtWidgets.QWidget(self)
- self.hLayoutWidget.setGeometry(QtCore.QRect(10, 650, 700, 41))
- self.hLayoutWidget.setObjectName("horizontalLayoutWidget")
- self.hLayout = QtWidgets.QHBoxLayout(self.hLayoutWidget)
- self.hLayout.setObjectName("horizontalLayout")
- self.groupBox_2 = QtWidgets.QGroupBox(self.hLayoutWidget)
- self.groupBox_2.setSizePolicy(self.mySetsizePolicy(4))
- self.groupBox_2.setTitle("")
- self.groupBox_2.setObjectName("groupBox_2")
- self.hLayout.addWidget(self.groupBox_2)
- #添加按钮
- spacerItem0 = QtWidgets.QSpacerItem(40, 20,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Minimum)
- self.hLayout.addItem(spacerItem0)
- self.Btn_start = QtWidgets.QPushButton(self.hLayoutWidget)
- self.Btn_start.setObjectName("Btn_start")
- self.hLayout.addWidget(self.Btn_start)
- spacerItem = QtWidgets.QSpacerItem(40, 20,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Minimum)
- self.hLayout.addItem(spacerItem)
- self.Btn_close = QtWidgets.QPushButton(self.hLayoutWidget)
- self.Btn_close.setObjectName("Btn_close")
- self.hLayout.addWidget(self.Btn_close)
- spacerItem1 = QtWidgets.QSpacerItem(40, 20,
- QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Minimum)
- self.hLayout.addItem(spacerItem1)
- self.Btn_start.setText(_translate("Dialog", "开始"))
- self.Btn_close.setText(_translate("Dialog", "结束"))
- self.main_widget.setFocus()
- self.setCentralWidget(self.main_widget)
- class WorkThread(QtCore.QThread):
- trigger = QtCore.pyqtSignal()
- ischange = False
- list_int_n = []
- def __int__(self):
- super(WorkThread, self).__init__()
- def run(self):
- while True:
- #print(self.ischange)
- if self.ischange:
- try:
- self.instrument = minimalmodbus.Instrument('com2', 4)
- self.instrument.serial.baudrate = 9600
- self.list_int_n = self.instrument.read_registers(0, 8, 4)
- except:
- self.trigger.emit()
- self.ischange = False
- time.sleep(1)
- #print(self.ischange)
- print(self.list_int_n)
- #self.trigger.emit() # 循环完毕后发出信号
- class myWindow(ApplicationWindow):
- def __init__(self):
- super(myWindow,self).__init__()
- self.Btn_start.clicked.connect(self.mystart)
- self.int_n =[]
- self.x = []
- self.y1 = []
- self.y2 = []
- self.time = time.time()
- self.timer = QtCore.QTimer()
- self.recordtimer = QtCore.QTimer()
- self.workThread = WorkThread()
- self.workThread1 = WorkThread()
- self.Btn_start.clicked.connect(self.mystart)
- self.timer.timeout.connect(self.myrun)
- self.recordtimer.timeout.connect(self.myrecord)
- self.ischange = False
- def mystart(self):
- self.timer.start(200)
- self.workThread.start()
- self.recordtimer.start(1000)
- self.time = time.time()
- #self.workThread1.start()
- #self.workThread.trigger.connect(self.timeStop)
- self.ischange = True
- def myrun(self):
- self.workThread.trigger.connect(self.showErrorDialog)
- self.workThread.ischange = self.ischange
- self.int_n = self.workThread.list_int_n
- #print(self.int_n)
- if len(self.int_n) >=8:
- for i in range(8):
- self.myLCD[i].display('{:.2f}'.format(self.int_n[i]))
- def showErrorDialog(self):
- self.workThread.ischange = False
- self.ischange = False
- self.timer.stop()
- self.recordtimer.stop()
- #time.sleep(1)
- self.errorwindow = errorDialog()
- self.errorwindow.show()
- def myrecord(self):
- if self.ischange and len(self.int_n)>=8 :
- if len(self.x)>=101:
- self.x = self.x[1:]
- self.x.append(time.time() - self.time)
- if len(self.y1) >= 101:
- self.y1 = self.y1[1:]
- self.y1.append(self.int_n[0])
- if len(self.y2) >= 101:
- self.y2 = self.y2[1:]
- self.y2.append(self.int_n[1])
- self.myFigure.x = self.x
- self.myFigure.y1 = self.y1
- self.myFigure.y2 = self.y2
- pass
- app = QtWidgets.QApplication(sys.argv)
- myWindow = myWindow()
- myWindow.show()
- sys.exit(app.exec_())
复制代码
|
|