我完全不知道是什么导致了这个问题,所以希望这里有人可以提供帮助。基本上,我使用 PyQt5 构建了一个 GUI 应用程序,当作为 .py 文件运行时,它可以完美运行,完全没有错误,但是当我使用 cx_freeze 将其转换为 .exe 文件时,我的绘图函数中断,返回错误:
Traceback (most recent call last):
File "main2.py", line 266, in randomForest
File "C:\Users\tyler\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\plotting\_core.py", line 972, in __call__
return plot_backend.plot(data, kind=kind, **kwargs)
AttributeError: module 'pandas.plotting._matplotlib' has no attribute 'plot'
同样,此函数在 .py 文件中有效,但在 .exe 中无效。下面是它尝试运行的相关代码。
# Importing modules / libraries
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as Navi
from matplotlib.figure import Figure
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn import svm
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
import sip
from sklearn.ensemble import IsolationForest
from sklearn.svm import OneClassSVM
# Canvas class to display the graph
class MatplotlibCanvas(FigureCanvasQTAgg):
# Setting graph dimensions
def __init__(self,parent=None, dpi = 120):
# Creating figure
fig = Figure(dpi = dpi)
# Create axes and add them to the figure as subplots
self.axes = fig.add_subplot(111)
super(MatplotlibCanvas,self).__init__(fig)
# Setting figure layout
fig.tight_layout()
# UI class
class Ui_MainWindow(object):
# Create UI
def setupUi(self, MainWindow):
# Create MainWindow
MainWindow.setObjectName("MainWindow")
MainWindow.resize(947, 633)
# Create centralwidget
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# Layout centralwidget in a grid
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
# Create horizontal layout to hold the buttons
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
# Button to activate the random forest classifier, and it to the horizontal layout
self.randomForestButton = QtWidgets.QPushButton(self.centralwidget)
self.randomForestButton.setObjectName("randomForestButton")
self.horizontalLayout.addWidget(self.randomForestButton)
# Button to activate the SVM classifier, and it to the horizontal layout
self.svmButton = QtWidgets.QPushButton(self.centralwidget)
self.svmButton.setObjectName("svmButton")
self.horizontalLayout.addWidget(self.svmButton)
# Button to activate the isolation forest algorithm, and it to the horizontal layout
self.isolationForestButton = QtWidgets.QPushButton(self.centralwidget)
self.isolationForestButton.setObjectName("isolationForestButton")
self.horizontalLayout.addWidget(self.isolationForestButton)
# Button to activate the One-Class SVM algorithm, and it to the horizontal layout
self.oneclassSVMButton = QtWidgets.QPushButton(self.centralwidget)
self.oneclassSVMButton.setObjectName("oneclassSVMButton")
self.horizontalLayout.addWidget(self.oneclassSVMButton)
# Create horizontal spacer
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
# Specifying dimensions of the horizontal layout
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
# Create second horizontal layout for the labels
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
for i in range(101):
self.comboBox.addItem("")
self.horizontalLayout_2.addWidget(self.comboBox)
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setObjectName("label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.comboBox_2 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox_2.setObjectName("comboBox_2")
for i in range(101):
self.comboBox_2.addItem("")
self.horizontalLayout_2.addWidget(self.comboBox_2)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setObjectName("label_3")
self.horizontalLayout_2.addWidget(self.label_3)
self.comboBox_3 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox_3.setObjectName("comboBox_3")
for i in range(101):
self.comboBox_3.addItem("")
self.horizontalLayout_2.addWidget(self.comboBox_3)
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setObjectName("label_4")
self.horizontalLayout_2.addWidget(self.label_4)
self.comboBox_4 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox_4.setObjectName("comboBox_4")
for i in range(101):
self.comboBox_4.addItem("")
self.horizontalLayout_2.addWidget(self.comboBox_4)
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setObjectName("label_5")
self.horizontalLayout_2.addWidget(self.label_5)
self.comboBox_5 = QtWidgets.QComboBox(self.centralwidget)
self.comboBox_5.setObjectName("comboBox_5")
for i in range(5):
self.comboBox_5.addItem("")
self.horizontalLayout_2.addWidget(self.comboBox_5)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem1)
self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(self.spacerItem2)
self.gridLayout.addLayout(self.verticalLayout, 2, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 947, 26))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionOpen_CSV_File = QtWidgets.QAction(MainWindow)
self.actionOpen_CSV_File.setObjectName("actionOpen_CSV_File")
self.actionExit = QtWidgets.QAction(MainWindow)
self.actionExit.setObjectName("actionExit")
self.menuFile.addAction(self.actionOpen_CSV_File)
self.menuFile.addAction(self.actionExit)
self.menubar.addAction(self.menuFile.menuAction())
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.randomForestButton.setText(_translate("MainWindow", "Random Forest"))
self.svmButton.setText(_translate("MainWindow", "SVM"))
self.isolationForestButton.setText(_translate("MainWindow", "Isolation Forest"))
self.oneclassSVMButton.setText(_translate("MainWindow", "One-Class SVM"))
self.label.setText(_translate("MainWindow", "test_size"))
self.label_2.setText(_translate("MainWindow", "random_state (train/test split)"))
self.label_3.setText(_translate("MainWindow", "n_estimators"))
self.label_4.setText(_translate("MainWindow", "random_state (classifier)"))
self.label_5.setText(_translate("MainWindow", "kernel"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.actionOpen_CSV_File.setText(_translate("MainWindow", "Open CSV File"))
self.actionExit.setText(_translate("MainWindow", "Exit"))
self.iterator1 = 0
self.iterator2 = 0
self.num1 = 0.0
self.num2 = 0
for i in range(101):
self.comboBox.setItemText(self.iterator1, _translate("MainWindow", str(round(self.num1, 2))))
self.iterator1 += 1
self.num1 += 0.01
for i in range(101):
self.comboBox_2.setItemText(self.iterator2, _translate("MainWindow", str(round(self.num2, 2))))
self.comboBox_3.setItemText(self.iterator2, _translate("MainWindow", str(round(self.num2, 2))))
self.comboBox_4.setItemText(self.iterator2, _translate("MainWindow", str(round(self.num2, 2))))
self.iterator2 += 1
self.num2 += 1
self.comboBox_5.setItemText(0, _translate("MainWindow", "linear"))
self.comboBox_5.setItemText(1, _translate("MainWindow", "poly"))
self.comboBox_5.setItemText(2, _translate("MainWindow", "rbf"))
self.comboBox_5.setItemText(3, _translate("MainWindow", "sigmoid"))
self.comboBox_5.setItemText(4, _translate("MainWindow", "precomputed"))
self.filename = ''
self.canv = MatplotlibCanvas(self)
self.actionOpen_CSV_File.triggered.connect(self.getFile)
self.randomForestButton.clicked.connect(self.randomForest)
self.svmButton.clicked.connect(self.SVM)
self.isolationForestButton.clicked.connect(self.isolationForest)
self.oneclassSVMButton.clicked.connect(self.oneclassSVM)
def getFile(self):
self.filename = QFileDialog.getOpenFileName(filter = "csv (*.csv)")[0]
self.df = pd.read_csv(self.filename,encoding = 'utf-8').fillna(0)
def randomForest(self):
# Random forest classifier for the machine temperature system failure data
y = self.df['Fault'].values
X = self.df.drop(['Fault'], axis = 1)
# Establishing training and testing sets.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = float(self.comboBox.currentText()), random_state = int(self.comboBox_2.currentText()))
# Defining the random forest classifier and fitting the model to the data
model = RandomForestClassifier(n_estimators = int(self.comboBox_3.currentText()), random_state = int(self.comboBox_4.currentText()))
model.fit(X_train, y_train)
# Predicting the classes
prediction_test = model.predict(X_test)
accuracy = metrics.accuracy_score(y_test, prediction_test)
percentage = "{:.2%}".format(accuracy)
# Displaying prediction accuracy
print("Accuracy = ", percentage)
self.toolbar = Navi(self.canv,self.centralwidget)
try:
self.horizontalLayout.removeWidget(self.toolbar)
self.verticalLayout.removeWidget(self.canv)
sip.delete(self.toolbar)
sip.delete(self.canv)
self.toolbar = None
self.canv = None
self.verticalLayout.removeItem(self.spacerItem2)
except Exception as e:
print(e)
pass
self.canv = MatplotlibCanvas(self)
self.verticalLayout.addWidget(self.canv)
self.canv.axes.cla()
self.ax = self.canv.axes
if self.filename.find("temperature.csv") != -1:
self.df = pd.read_csv("machine_temperature_system_failure.csv")
self.df.plot(ax = self.canv.axes)
self.ax.set_xlabel('timestamp')
self.ax.set_ylabel('values')
self.ax.set_title(str(percentage))
self.ax.get_legend().remove()
self.canv.draw()
else:
self.df.plot(ax = self.canv.axes)
self.ax.set_xlabel('timestamp')
self.ax.set_ylabel('values')
self.ax.set_title(str(percentage))
self.ax.get_legend().remove()
self.canv.draw()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
根据我在这里看到的类似问题,我尝试过一些事情:
将 matplotlib.pyplot 导入为 plt
卸载、更新和重新安装 pandas。
卸载并重新安装 matplotlib
我使用 pyinstaller、cx_freeze 和 py2exe 生成了 .exe,但所有这些都出现了错误。 cx_freeze 是我更喜欢使用的。
我知道这个问题已经近两年没有持续了,但我在使用 python 包“cx_Freeze”冻结我用 python 的“Tkinter”开发的应用程序时遇到了完全相同的错误。
我可以通过更改
setup.py
脚本来解决这个问题。在 cx_Freeze.setup()
函数的选项部分,在“build_exe”内可以明确包含任何包,特别是对于第三方包。
这是一个
setup.py
脚本的示例,我在其中包含了 packages_included
一些给我带来麻烦的包:
import cx_Freeze
import sys
import matplotlib
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
executables = [cx_Freeze.Executable("main.py", base=base, icon='Logo.ico')]
packages_included = ["tkinter", "matplotlib", "seaborn", "cefpython3", "dash",
"pyodbc","numpy", "pandas", "pandastable"]
packages_excluded = ["scipy", "skimage", "scikit-learn","xlsxwriter", "xml",
"xmlrpc","xarray", "tables", "statsmodels","sqlalchemy",
"tornado","sphinx", "openpyxl", "lxml","jupyter_core",
"jupyter_server", "jupyter_client",
"ipykernel", "ipython_genutils","ipywidgets", "h5py",
"distributed","defusedxml", "dask",
"docutils","cryptography", "bs4"]
cx_Freeze.setup(
name = "Risk Tracker",
options = {"build_exe": {"packages":packages_included,
"excludes":packages_excluded,
"include_files":["Logo.png", "Logo.ico"]}},
version = '0.01',
description = "Application for tracking risk",
executables = executables
)
事实上,某些包的依赖项出现的一些问题,例如循环导入错误(如“seaborn”或“pandastable”)或缺少模块,只需显式包含该包即可解决。