| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3711 人关注过本帖
标题:用py2exe打包PyQt5+Matplotlib出错
只看楼主 加入收藏
calebwzy1986
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2016-8-26
收藏
 问题点数:0 回复次数:0 
用py2exe打包PyQt5+Matplotlib出错
打包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)

        ()

        #
        #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_())
搜索更多相关主题的帖子: recent 信息 
2016-08-26 23:07
快速回复:用py2exe打包PyQt5+Matplotlib出错
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.225425 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved