While-loop expected an indented block - while-loop

import win32api, win32con
import time
def click(x,y):
while True:
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
click(1304,52)
time.sleep(1)
click(966,630)
time.sleep(0.2)
click(1109,720)

Related

ThreadPoolExecutor DataFrame

I am dealing with a simple loop.
I have a slightly larger dataframe and I would like to use the processor (currently 2%).
I tried this:
import pandas as pd
import numpy as np
import time
from concurrent.futures import ThreadPoolExecutor
scan = pd.DataFrame([[0,2,3,5],[4,2,7,7], [5,6,2,3]], columns=['st1','nd1','st2','nd2'])
def task(value):
calc_all = pd.DataFrame()
for i in range(0,3,2):
j=i+1
calc = pd.concat([pd.DataFrame(scan.iloc[:,i]), pd.DataFrame(scan.iloc[:,j])],axis=1)
calc['th'] = calc.iloc[:,0] + calc.iloc[:,1]
calc_all = pd.concat([calc_all, calc], axis=1)
time.sleep(1) #tested time
return calc_all
if __name__ == '__main__':
with ThreadPoolExecutor(2) as exe:
for result in exe.map(task, range(2)):
print(result)
It's not faster. What did I do wrong?

PyQt5 Signal Between Classes Causing Lockup

I'm trying to send signals between classes, which works fine from the HMI class to the WorkerThread class, but causes a program lockup, or infinite loop, when WorkerThread tries to connect to a signal from the HMI class.
import sys
import time
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QWidget, QApplication
from Home import Ui_HomeWin # PyQt5 Designer window
class WorkerThread(QThread):
hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.counter = 0
# this attempted connection causes a lockup
self.HMI_Thread = HMI() # appears to be a recursive loop
self.HMI_Thread.updateGlobals.connect(self.update_global_widgets)
def run(self):
while True:
time.sleep(0.5)
print('Doing a bunch of other stuff: {}'.format(self.counter))
self.counter += 1
def build_a_command(self):
print('building a command...')
name = 'pbAutoMode'
# example command
command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
self.hmiHandlesThis.emit(command)
def update_global_widgets(self):
print('update some global widgets')
class HMI(QWidget):
updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
def __init__(self, parent=None):
super(HMI, self).__init__(parent)
self.HomeWin = QtWidgets.QDialog()
self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
ui = Ui_HomeWin()
ui.setupUi(self.HomeWin)
self.HomeWin.show()
# this connection works
self.workerThread = WorkerThread()
self.workerThread.hmiHandlesThis.connect(self.on_new_command)
self.workerThread.start()
def on_new_command(self, command):
print('New command is: {}'.format(command))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = HMI()
sys.exit(app.exec_())~~~
I've tried placing the signal definitions inside the init functions, with no difference.
With Dennis Jensen's help, i've been able to get this running properly. I'm posting the working snippet here as an example of 'proper' thread building and the passing of signals.
import sys
import time
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtWidgets import QWidget, QApplication
from Home import Ui_HomeWin # a PyQt5 Designer window
class WorkerThread(QObject):
hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str, str)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.counter = 0
def processRun(self):
while True:
time.sleep(0.5)
print('Doing a bunch of other stuff: {}'.format(self.counter))
self.counter += 1
def update_global_widgets(self):
print('update some global widgets')
def build_a_command(self):
print('building a command...')
name = 'pbAutoMode'
# example command
command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
self.hmiHandlesThis.emit(name, command)
class HMI(QWidget):
updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
def __init__(self, parent=None):
super(HMI, self).__init__(parent)
self.HomeWin = QtWidgets.QDialog()
self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
ui = Ui_HomeWin()
ui.setupUi(self.HomeWin)
self.HomeWin.show()
self.EstablishThread()
def EstablishThread(self):
# Create the Object from Class
self.Worker = WorkerThread()
# Assign the Database Signals to Slots
self.Worker.hmiHandlesThis.connect(self.on_new_command)
# Create the Thread
self.ThredHolder = QThread()
# Move the Listener to the Thread
self.Worker.moveToThread(self.ThredHolder)
# Assign the Listener Starting Function to the Thread Call
self.ThredHolder.started.connect(self.Worker.processRun)
# Start the Thread which launches Listener.Connect( )
self.ThredHolder.start()
def on_new_command(self):
print('Handling new command...')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = HMI()
sys.exit(app.exec_())
Thanks Dennis!

cannot plot lines on matplotlib embedded in pyqt5

Following is the codes. It plots a line via pressing a button. However, when I pressed the button, it just printed
matplotlib.lines.Line2D object at 0x11371fcc0 ......
but could not show the line on the canvas. How do you fix it?
import matplotlib
matplotlib.use("Qt5Agg")
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import mywidgets
# mywidgets.MplCanvas is a wrapper of FigureCanvas in order to make the drawing convenient.
class ApplicationWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("Hello")
self.main_widget = QWidget(self)
l = QVBoxLayout(self.main_widget)
fig1 = Figure(figsize=(5, 4))
self.sc = mywidgets.MplCanvas(self.main_widget, fig1)
l.addWidget(self.sc)
bdraw = QPushButton('Draw')
bdraw.pressed.connect(self.draw)
l.addWidget(bdraw)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
def draw(self):
# it does not report any error, but on lines are drawn.
line = self.sc.axes.plot([1,2,3], 'r')
print(line)
if __name__ == '__main__':
app = QApplication([])
aw = ApplicationWindow()
aw.show()
#sys.exit(qApp.exec_())
app.exec_()
You forgot to update the canvas after plotting to it.
def draw(self):
line = self.sc.axes.plot([1,2,3], 'r')
self.sc.draw_idle()

How to implement QThread correctly with matplotlib and pyplot

I understand that there have been one or two other questions posted that are related but not exactly what I need. I'm building this gui that activates a module by clicking a button. This python module that gets activated by pushing the button generates heatmaps from multiple pandas dataframes and saves those images, which in turn is then saved into an xlsx using pandas ExcelWriter.
I've tried to implement QThread, as other stackoverflow examples tried to explain similar problems but I continue getting this error: "It is not safe to use pixmaps outside the GUI thread". I understand that technically I'm not creating the heatmap inside the MAIN gui thread but I thought with QThread that I am still inside "a" gui thread. These dataframes that the heatmaps are based off of can be of a large size at times and I am somewhat grasping the concept of sending a signal to the main gui thread when a heatmap is to be created and have the heatmap function inside the main gui class...but I fear that will be troublesome later in passing so much data around..this is more like pipelining than threading. I just want this working thread to create these images and save them and then take those saved files and save them into an xlsx without interrupting the main gui..
(NOTE: This is a simplified version, in the real program there will be several of these threads created almost simultaneously and inside each thread several heatmaps will be created)
---main.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_())
---excel_dummy.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---
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))
Even though you are explicitely using the Agg backend to generate your figure, it looks like Seaborn is still using the default backend on your system, which is most likely Qt4Agg, an interactive backend. We want Seaborn to use a non-interactive backend instead to avoid any error (see matplotlib documentation for more details about backends). To do so, tell Matplotlib in your imports to use the Agg backend and import Seaborn after Matplotlib.
You will also need to save your figure as a png, since jpg is not supported by the Agg backend. Unless you have some specific reasons for using jpg, png is usually a better format for graphs.
Finally, you could use a memory buffer instead of saving your images to a temporary file before saving them in an Excel Workbook. I haven't tested it, but it will probably be faster if you are working with large files.
Below is a MWE I've written which includes the aformentioned points and which does not give any error on my system in Python3.4:
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_())

How to change ipython qtconsole input

I'm making a guide with pyqt and I'm including an ipython qtconsole widget.
try:
from qtconsole.rich_jupyter_widget import RichJupyterWidget as ipythonWidget
from qtconsole.inprocess import QtInProcessKernelManager
except:
from IPython.qt.console.rich_ipython_widget import RichIPythonWidget as ipythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager
I want to modify the qtconsole input from my code but is not working. I've tried the set_next_input function but it doesn't work and I can't find another function I can use to acomplish what I want. Is even possible to achieve what I want? and if so, how can I do it?
Here is my code:
try:
from qtconsole.rich_jupyter_widget import RichJupyterWidget as ipythonWidget
from qtconsole.inprocess import QtInProcessKernelManager
except:
from IPython.qt.console.rich_ipython_widget import RichIPythonWidget as ipythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager
import sys
from PyQt4 import QtGui
class sympyIpython(QtGui.QWidget):
def __init__(self):
super().__init__()
self.ipython = IpythonWidget()
v = QtGui.QVBoxLayout(self)
button = QtGui.QPushButton('append to input')
v.addWidget(self.ipython)
v.addWidget(button)
button.clicked.connect(self.symClicked)
def symClicked(self):
self.ipython.kernel.shell.set_next_input(' appended text')
class IpythonWidget(ipythonWidget):
def __init__(self):
super().__init__()
self.kernel_manager = QtInProcessKernelManager()
self.kernel_manager.start_kernel()
self.kernel = self.kernel_manager.kernel
self.kernel.gui = 'qt4'
self.kernel_client = self.kernel_manager.client()
self.kernel_client.start_channels()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
m = sympyIpython()
m.show()
sys.exit(app.exec_())
Reposting as an answer:
To change the text at the prompt in the Qt console, set input_buffer on the widget object:
jupyter_widget.input_buffer = 'text'