2016-10-18 9 views
2

私は、関連するものの、正確には私が必要とするものではない1つまたは2つの質問が掲載されていることを理解します。私はボタンをクリックしてモジュールをアクティブにするGUIを構築しています。このボタンを押すことによってアクティブになるこのPythonモジュールは、複数のパンダデータフレームからヒートマップを生成し、それらの画像を保存します。これらの画像は、次にpandas ExcelWriterを使用してxlsxに保存されます。matplotlibとpyplotを使ってQThreadを正しく実装する方法

QThreadを実装しようとしましたが、他のstackoverflowの例で同様の問題を説明しようとしましたが、このエラーが発生し続けます。"It is not safe to use pixmaps outside the GUI thread"技術的には私はMAIN GUIスレッドの内部にヒートマップを作成していないが、QThreadではまだ "a" GUIスレッド内にあると思った。ヒートマップがベースになっているこれらのデータフレームは、時には大きなサイズになる可能性があります。ヒートマップを作成し、メインGUIクラス内にヒートマップ機能を持たせる場合、メインGUIスレッドにシグナルを送信するという概念を幾分把握しています...しかし、あまりにも多くのデータを渡すのが後で面倒になるのではないかと恐れています。これはスレッディングよりもパイプライニングに似ています。私はちょうどこの作業スレッドがこれらのイメージを作成し、それらを保存し、それらを保存し、メインのGUIを中断することなくxlsxにそれらを保存します。

(注:これは、 excel_dummy.py --- ---

import sys 
from MAIN_GUI import * 
from PyQt4 import QtGui, QtCore 
from excel_dummy import * 

if __name__=="__main__": 
    app = QtGui.QApplication(sys.argv) 


class MAIN_GUI(QtGui.QMainWindow): 
    def __init__(self): 
     super(MAIN_GUI, self).__init__() 
     self.uiM = Ui_MainWindow() 
     self.uiM.setupUi(self) 
     self.connect(self.uiM.updateALL_Button,QtCore.SIGNAL('clicked()'),self.newThread) 

    def newThread(self): 
     Excelify = excelify() 
     Excelify.start() 
     self.connect(Excelify,QtCore.SIGNAL('donethread(QString)'),(self.done)) 

    def done(self): 
     print('done') 


main_gui = MAIN_GUI() 
main_gui.show() 
main_gui.raise_() 
sys.exit(app.exec_()) 

ほぼ同時に、いくつかのヒートマップが作成される各スレッド)

--- main.py内に作成これらのスレッドのいくつかであろう---

import os, pandas as pd 
from pandas import ExcelWriter 
import numpy as np 
import seaborn.matrix as sm 

from PyQt4 import QtCore 
from PyQt4.QtCore import QThread 
from matplotlib.backends.backend_agg import FigureCanvas 
from matplotlib.figure import Figure 
import time 

class excelify(QThread): 
    def __init__(self): 
     QThread.__init__(self) 

    def run(self): 
     path = 'home/desktop/produced_files' 
     with ExcelWriter(path + '/final.xlsx', engine='xlsxwriter') as writer: 
      workbook = writer.book 
      worksheet = workbook.add_worksheet() 
      heatit = self.heatmap() 
      worksheet.insert_image('C3',path + '/' + 'heat.jpg') 
      worksheet.write(2, 2, 'just write something') 
      writer.save() 
     print('file size: %s "%s"' % (os.stat(path).st_size, path)) 
     time.slee(0.3) 
     self.emit(QtCore.SIGNAL('donethread(QString)'),'') 

    def heatmap(self): 
     df = pd.DataFrame(np.array([[1,22222,33333],[2,44444,55555],[3,44444,22222],[4,55555,33333]]),columns=['hour','in','out']) 
     dfu = pd.DataFrame(df.groupby([df.in,df.hour]).size()) 
     dfu.reset_index(inplace=True) 
     dfu.rename(columns={'0':'Count'}) 
     dfu.columns=['in','hour','Count'] 
     dfu_2 = dfu.copy() 

     mask=0 
     fig = Figure() 
     ax = fig.add_subplot(1,1,1) 
     canvas = FigureCanvas(fig) 
     df_heatmap = dfu_2.pivot('in','hour','Count').fillna(0) 

     sm.heatmap(df_heatmap,ax=ax,square=True,annot=False,mask=mask) 
     fig.savefig(path + '/' + heat.jpg') 

--- MAIN_GUI.py ---あなたが明示的に自分の姿を生成するAggバックエンドを使用しているにもかかわらず

from PyQt4 import QtCore,QtGui 
try: 
    _fromUtf8 = QtCore.QString.fromUtf8 
except AttributeError: 
    def _fromUtf8(s): 
     return s 

try: 
    _encoding = QtGui.QApplication.unicodeUTF8 
    def _translate(context, text, disambig): 
     return QtGui.QApplication.translate(context, text, disambig, _encoding) 
except AttributeError: 
    def _translate(context, text, disambig): 
     return QtGui.QApplication.translate(context, text, disambig) 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName(_fromUtf8("MainWindow")) 
     MainWindow.resize(320,201) 
     self.centralwidget = QtGui.QWidget(MainWindow) 
     self.centralwidget.setObjectName(_fromUtf8("centralwidget")) 
     self.updateALL_Button = QtGui.QPushButton(self.centralwidget) 
     self.updateALL_Button.setGeometry(QtCore.QRect(40,110,161,27)) 
     self.updateALL_Button.setFocusPolicy(QtCore.Qt.NoFocus) 
     self.updateALL_Button.setObjectName(_fromUtf8("Options_updateALL_Button")) 
     MainWindow.setCentralWidget(self.centralwidget) 
     self.menubar = QtGui.QMenuBar(MainWindow) 
     self.menubar.setGeometry(QtCore.QRect(0, 0, 320, 24)) 
     self.menubar.setObjectName(_fromUtf8("menubar")) 
     MainWindow.setMenuBar(self.menubar) 
     self.statusbar = QtGui.QStatusBar(MainWindow) 
     self.statusbar.setObjectName(_fromUtf8("statusbar")) 
     MainWindow.setStatusBar(self.statusbar) 

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

    def retranslateUi(self,MainWindow): 
     MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) 
     self.updateALL_Button.setText(_translate("MainWindow", "updateALL", None)) 

答えて

1

が、それはまだ可能性が高いです、あなたのシステム上のデフォルトのバックエンドを使用しているSeabornように見えますQt4Agg、インタラクティブバックエンドSeabornはエラーを避けるためにnon-interactive backendを使用します(バックエンドの詳細については、matplotlib documentationを参照してください)。これを行うには、インポートのMatplotlibAggバックエンドを使用し、 Matplotlibの後にSeaborn をインポートするように指示します。

Aggバックエンドでjpgがサポートされていないため、図をpngとして保存する必要があります。 jpgを使用する特定の理由がない限り、pngは通常グラフのより良いフォーマットです。

最後に、イメージを一時ファイルに保存する代わりに、メモリブックを使用してExcelブックに保存することもできます。私はそれをテストしていませんが、大きなファイルを扱っている方が速いでしょう。

以下

私はaformentionedポイントを含むとPython3.4での私のシステム上の任意のエラーを与えない書いたMWEです:あなたはSir.THANK、

import pandas as pd 
import time 
from pandas import ExcelWriter 
import numpy as np 
from PyQt4 import QtCore, QtGui 

import matplotlib as mpl 
mpl.use('Agg') 
from matplotlib.backends.backend_agg import FigureCanvas 
import seaborn.matrix as sm 

try: # Python 2 (not tested) 
    from cStringIO import StringIO as BytesIO 
except ImportError: # Python 3 
    from io import BytesIO 


class MAIN_GUI(QtGui.QWidget): 
    def __init__(self): 
     super(MAIN_GUI, self).__init__() 

     self.worker = Excelify() 

     btn = QtGui.QPushButton('Run') 
     disp = QtGui.QLabel() 

     self.setLayout(QtGui.QGridLayout()) 
     self.layout().addWidget(btn, 0, 0) 
     self.layout().addWidget(disp, 2, 0) 
     self.layout().setRowStretch(1, 100) 

     btn.clicked.connect(self.worker.start) 
     self.worker.figSaved.connect(disp.setText) 


class Excelify(QtCore.QThread): 

    figSaved = QtCore.pyqtSignal(str) 

    def run(self): 
     self.figSaved.emit('Saving figure to Workbook.')  
     t1 = time.clock() 

     image_data = self.heatmap() 
     with ExcelWriter('final.xlsx', engine='xlsxwriter') as writer: 
      wb = writer.book 
      ws = wb.add_worksheet() 
      ws.insert_image('C3', 'heat.png', {'image_data': image_data}) 
      writer.save() 

     t2 = time.clock()  
     self.figSaved.emit('Done in %f sec.' % (t2-t1)) 

    def heatmap(self):  
     df = pd.DataFrame(np.array([[1, 22222, 33333], [2, 44444, 55555], 
            [3, 44444, 22222], [4, 55555, 33333]]), 
          columns=['hour', 'in', 'out']) 
     dfu = pd.DataFrame(df.groupby([df.out, df.hour]).size()) 
     dfu.reset_index(inplace=True) 
     dfu.rename(columns={'0': 'Count'}) 
     dfu.columns = ['in', 'hour', 'Count'] 

     fig = mpl.figure.Figure() 
     fig.set_canvas(FigureCanvas(fig)) 
     ax = fig.add_subplot(111) 

     df_heatmap = dfu.pivot('in', 'hour', 'Count').fillna(0) 
     sm.heatmap(df_heatmap, ax=ax, square=True, annot=False, mask=0) 

     buf= BytesIO() 
     fig.savefig(buf, format='png') 

     return(buf) 


if __name__ == '__main__': 
    import sys 

    app = QtGui.QApplication(sys.argv) 
    w = MAIN_GUI() 
    w.show() 
    w.setFixedSize(200, 100) 
    sys.exit(app.exec_()) 
+0

あなたはお金で正しかったです – Daniel

関連する問題