These are my first steps with python and desktop programming. I worked with web all my life and now I need to do threading.
I tried work with tkinter, pyqt and now gtk(father of tkinter) with glade xml.
I tried different modules because I was failing every time on the same problem. The interface has an infinite loop so I read a little bit about it on Google and its my first time working with python, desktop and threading
so here's my code could someone say what is wrong and why?
# -*- coding: utf-8 -*-
#Parallelism modulos
import threading
import Queue
#GUI modulos
import gtk, sys
#webservice modulos
import urllib2, json, urllib
#rfid modulos
import MFRC522
import signal
#GPIO modulos
import RPi.GPIO as GPIO
#sleep modulos
from time import sleep
#database modulos
import psycopg2
class Janela(threading.Thread):
def on_window_destroy(self, data=None):
gtk.main_quit()
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
builder = gtk.Builder()
builder.add_from_file("interface.glade")
self.window = builder.get_object("window1")
'''aluno informação'''
self.alunoimage = builder.get_object("alunoimage")
self.label = builder.get_object("nomecrianca")
'''Responsavel informação'''
builder.connect_signals(self)
imagefile = "anderson_caricatura.png"
self.alunoimage.set_from_file(imagefile)
self.label.set_text("Anderson Santana")
self.window.show()
gtk.main()
class RfID():
def __init__(self):
a = "343511711127"
self.read()
def beep(self):
GPIO.setup(11, GPIO.OUT)
GPIO.output(11, False)
sleep(0.05)
GPIO.output(11, True)
sleep(0.05)
GPIO.output(11, False)
sleep(0.05)
GPIO.output(11, True)
def regulariza_cartao(self,cartao):
string = ''.join(str(e) for e in cartao);
return string
def consulta_web_service(self,cartao):
req = urllib2.Request("http://192.168.1.161/ieduca/TheClientRfid.php?cartao="+cartao)
response = urllib2.urlopen(req)
the_page = response.read()
return the_page
def end_read(signal, frame):
MIFAREReader = MFRC522.MFRC522()
global continue_reading
continue_reading = False
print "Ctrl+C captured, ending read."
MIFAREReader.GPIO_CLEEN()
def read(self):
continue_reading = True
MIFAREReader = MFRC522.MFRC522()
while continue_reading:
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
(status,backData) = MIFAREReader.MFRC522_Anticoll()
if status == MIFAREReader.MI_OK:
self.beep()
string = self.regulariza_cartao(backData)
consome = self.consulta_web_service(string)
jsonreaded = json.loads(consome)
print "Tem responsavel? ",jsonreaded['have_responsavel']
print "nome do estudante: ",jsonreaded['estudante_nome']
print "estudante imagem: ",jsonreaded['estudante_imagem']
print "imagem caminho: ",jsonreaded['estudante_caminho']
urllib.urlretrieve("http://192.168.1.161/ieduca/"+jsonreaded['estudante_caminho']+jsonreaded['estudante_imagem'], jsonreaded['estudante_imagem'])
print "baixou a imagem"
queue = Queue.Queue()
print "abriu comunicador"
worker = Janela(queue)
print "instanciou a janela"
worker.start()
print "iniciou a janela"
queue.put('quit')
print "pede pra sair 02"
print "rala!"
def run():
GUI = RfID()
run()
this code seems with what is happening to my code
import threading
from time import sleep
#lets pretend this class is the rfid class and will be the first to run
class RFid(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
i=0
d=True
while d:
print "oi"
i = i+1
print i
if i==10:
t2 = Gtk()#after some conditions in it while other class will run this class is the gtk (window, label, images)obs:no buttons
t2.start()
t2.join()
sleep(5)
del t2
#self.run() (or something or something meaning it)
#for example
##if ctrl+c:
##d = False
class Gtk(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:#here on the gtk theres a infinity while never ends but it should close the window after some secs and than back to while of first class
print "ola"
#to resume the rfid will open a window with information of the owner of the rfidcard on scream
#but when the information are opened gtk enter on a infinity loop wainting for a event it will never happen
#when it should close after 5 secs and when other card's owner pass show other window and this forever...
def main():
t1 = RFid()
t1.start()
if __name__ == '__main__':
main()
i hope you understand now
Related
I tried to implement a windows hook to grab foreground window event. This code is probably bad because I didnt understand much.
Can you tell me if that is better than a simple while loop that checks the foreground window every 0.1s for a change?
Is this code okay or just horrible?
How can I stop this "listener" when I want to close the app?
"""
Script using the Windows API to register for window focus changes and print the
titles of newly focused windows.
"""
#https://github.com/Danesprite/windows-fun/blob/master/window%20change%20listener.py
import sys
import time
import ctypes
import ctypes.wintypes
import threading
import six
import win32gui
class ObservableWindowChange(object):
def __init__(self):
self.__observers = []
def register_observer(self, observer):
self.__observers.append(observer)
def notify_observers(self, *args, **kwargs):
win_title = ''.join(args)
if win_title == '':
return ''
for observer in self.__observers:
observer.notify(win_title)
def start_event_listener(self):
# Create a WindowChangeEventListener object with this instance of
# ObservableWindowChange as a parameter (self)
listener = WindowChangeEventListener(self)
listener.listen_forever()
class IWindowChangeObserver(object):
"""
Base class for observing window changes
"""
def __init__(self, observable, interface=None):
observable.register_observer(self)
self.interface = interface
def notify(self, win_title):
raise NotImplementedError
class WindowChangeEventListener(object):
"""
WindowChangeEventListener
"""
def __init__(self, observable):
self.observable = observable
def listen_forever(self):
# This is to fix a problem with ascii encoding (windows with Unicode in
# their titles)
if six.PY2:
reload(sys)
sys.setdefaultencoding('utf8')
# Look here for DWORD event constants:
# http://stackoverflow.com/questions/15927262/convert-dword-event-constant-from-wineventproc-to-name-in-c-sharp
# Don't worry, they work for python too.
EVENT_SYSTEM_DIALOGSTART = 0x0010
WINEVENT_OUTOFCONTEXT = 0x0000
EVENT_SYSTEM_FOREGROUND = 0x0003
WINEVENT_SKIPOWNPROCESS = 0x0002
user32 = ctypes.windll.user32
ole32 = ctypes.windll.ole32
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool,
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
ole32.CoInitialize(0)
WinEventProcType = ctypes.WINFUNCTYPE(
None,
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
ctypes.wintypes.HWND,
ctypes.wintypes.LONG,
ctypes.wintypes.LONG,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD
)
def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread,
dwmsEventTime):
length = GetWindowTextLength(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
GetWindowText(hwnd, buff, length + 1)
# hwnd = GetForegroundWindow()
# Notify observers
self.observable.notify_observers(buff.value)
WinEventProc = WinEventProcType(callback)
user32.SetWinEventHook.restype = ctypes.wintypes.HANDLE
hook = user32.SetWinEventHook(
EVENT_SYSTEM_FOREGROUND,
EVENT_SYSTEM_FOREGROUND,
0,
WinEventProc,
0,
0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
)
if hook == 0:
print('SetWinEventHook failed')
exit(1)
msg = ctypes.wintypes.MSG()
while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
user32.TranslateMessageW(msg)
user32.DispatchMessageW(msg)
# Stopped receiving events, so clear up the winevent hook and uninitialise.
print('Stopped receiving new window change events. Exiting...')
user32.UnhookWinEvent(hook)
ole32.CoUninitialize()
class WindowObserver(IWindowChangeObserver):
def notify(self, win_text):
time.sleep(0.3)
win_hwnd = win32gui.GetForegroundWindow()
# print("Window '%s' focused" % win_text)
if self.interface:
self.interface.update_perso_and_visibility(win_hwnd)
def run(interface=None):
# Create an observable and an observer observing it
subject = ObservableWindowChange()
observer = WindowObserver(subject, interface=interface)
# Listen for window changes
subject.start_event_listener()
class ThreadListener(threading.Thread):
def __init__(self, interface=None):
threading.Thread.__init__(self)
self.interface = interface
self.start()
def run(self):
run(self.interface)
def kill(self):
print("kill")
if __name__ == '__main__':
# Start the 'run' method in a daemonized thread.
# t = threading.Thread(target=run)
# t.setDaemon(True)
# t.start()
t = ThreadListener(None)
# Keep the main thread running in a sleep loop until ctrl+c (SIGINT) is caught.
# Once the main thread terminates, all daemon threads will automatically
# terminate.
cpt=0
while True:
try:
time.sleep(0.1)
cpt+=1
if cpt>10:
t.kill()
except KeyboardInterrupt:
break
This is supposed to be a windows hook that detects the foreground window change. When the change occurs, the interface given as a parameter is updated.
It seems to work but sometimes the detection doesn't happen.
Thanks for your help
The context:
I'm building a Graphical Interface with Qt creator and the "behaviour" file in python. A test version of my GUI is:
The expected behaviour:
I am running 2 different threads which are referred to the same function with different input arguments. With the SELECTOR button I can assign the value of 1 or 2 to a variable (and display it)
The button Start thread enables the correct thread to start (the first time).
The loop should be turned off by the stop button by modifying the global running variable.
This is my code
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui, uic
import sys
import threading
import time
import Queue
running = False
first_thread = None
second_thread = None
form_class = uic.loadUiType("simple2.ui")[0]
q = Queue.Queue()
select = 0
def action(string, queue): #function called by threads
global running
while(running):
phrase = string
if queue.qsize() < 10:
queue.put(phrase)
#else:
# print queue.qsize()
class MyWindowClass(QtGui.QMainWindow, form_class):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
#buttons
self.startButton.clicked.connect(self.start_clicked)
self.stopButton.clicked.connect(self.stop_clicked)
self.selector.clicked.connect(self.sel_click)
#variables
self.first = False
self.second = False
#queue
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_phrase)
self.timer.start(1)
def start_clicked(self): #start button callback
global select
if select > 0:
global running
running = True
print "started"
if (not self.first) & (select == 1):
first_thread.start()
self.first = True
if (not self.second) & (select == 2):
second_thread.start()
self.second = True
self.startButton.setEnabled(False)
self.startButton.setText('Starting...')
def stop_clicked(self): #stop button callback
global running
running = False
print "stopped"
self.startButton.setEnabled(True)
self.startButton.setText('Start Thread')
def sel_click(self): #selector button callback
global select
if select < 2:
select = select + 1
else:
select = 1
self.thread_counter.setText(str(select))
def update_phrase(self): #looping function
global running
if (not q.empty()) & running:
self.startButton.setText('Thread on')
abc = q.get()
print abc
def closeEvent(self, event):
global running
running = False
if __name__ == "__main__":
first_thread = threading.Thread(target=action, args = ("first", q))
second_thread = threading.Thread(target=action, args = ("second", q))
app = QtGui.QApplication(sys.argv)
w = MyWindowClass(None)
w.setWindowTitle('Multiple threads test in python')
w.show()
app.exec_()
For now, each thread should simple print on terminal their arguments ("First" or "Second").
If threads are started for the first time, my code works. But I would like to switch between threads infinite times.
Since threads cannot be stopped, is there a way to "pause" them?
I cannot find a solution, I hope someone will help me also with a piece of code. Thank you in advance
You can use Lock class to do that, a simple example would be:
import threading
lock = threading.Lock()
//here it will be lock
lock.acquire() # will block if lock is already held
...
then in other side do
//this will wake up
lock.release()
you can read more here http://effbot.org/zone/thread-synchronization.htm
I have simple script for watchdog on network device. Script monitors response from PING command. If there is no answer then second thread executes and first thread is stopped. If second thread is finished then first thread is resumed (checking ping). If there is no answer then following message appears:
RuntimeError: threads can only be started once
Here is my code:
#!/usr/bin/python
import os
import time
import sqlite3
from ablib import Pin
import threading
led=Pin('W9','OUTPUT')
class threadout1(threading.Thread):
def run(self):
while True:
conn = sqlite3.connect('database/database.db')
cur = conn.cursor()
cur.execute("SELECT * FROM watchdog")
rows_output = cur.fetchall()
time.sleep(1)
if rows_output[0][1] == "ping":
response = os.system("ping -c 1 " + rows_output[0][2])
if response != 0:
print "bad"
rest.start()
rest.join()
class restart(threading.Thread):
def run(self):
led.on()
time.sleep(15)
led.off()
thr = threadout1()
rest = restart()
thr.start()
You can either create the restart thread every time you need it
if response != 0:
print "bad"
restart_thread = restart()
restart_thread.start()
restart_thread.join()
or use Events
class restart_thread(threading.Thread):
def __init__(self, evt):
self.evt = evt
def run(self):
self.evt.wait()
# do stuff
self.evt.clear()
class threadout(threading.Thread):
def __init__(self, evt):
self.evt = evt
def run(self):
if #other thread needs to run once
self.evt.set()
evt = threading.Event()
restart_thread = restart(evt)
restart_thread.start()
pinging_thread = threadout(evt)
pinging_thread.start()
To make the pinging_thread wait for the restart_thread to finish, you could use another Event.
I created the dbus server as the following code, named it as server1.py
#!/usr/bin/python2.7
import dbus.service
import dbus.glib
import glib
import gobject
from dbus.mainloop.glib import DBusGMainLoop
class APP_Server(dbus.service.Object):
def __init__(self):
bus = dbus.SessionBus(private = True, mainloop = DBusGMainLoop())
bus_name = dbus.service.BusName('de.test.app1', bus)
dbus.service.Object.__init__(self, bus_name, '/de/test/app1_obj_path')
#dbus.service.method("test.app1.interface",)
def is_ready(self):
return True
def publish_dbus():
loop = glib.MainLoop()
APP_Server()
loop.run()
if __name__ == '__main__':
gobject.threads_init()
dbus.glib.init_threads()
publish_dbus()
And then I want to access dbus service in the server1.py by the following code, named it as server2.py which also will work as a dbus server.
#!/usr/bin/python2.7
import dbus.service
import dbus.glib
import glib
import dbus.mainloop
import gobject
from dbus.mainloop.glib import DBusGMainLoop
from threading import Thread
from time import sleep
class APP_Server(dbus.service.Object):
def __init__(self):
bus = dbus.SessionBus(private = True, mainloop = DBusGMainLoop())
bus_name = dbus.service.BusName('de.test.app3', bus)
dbus.service.Object.__init__(self, bus_name, '/de/test/app3_obj_path')
#dbus.service.method("test.app3.interface",)
def is_ready(self):
return True
def call_dbus():
bus_name = 'de.test.app1'
obj_path = '/de/test/app1_obj_path'
interface_name = 'test.app1.interface'
count = 1
while count < 1000:
proxy_bus = dbus.SessionBus(private = True)
obj = None
try:
obj = proxy_bus.get_object(bus_name, obj_path)
except:
sleep(1)
obj = proxy_bus.get_object(bus_name, obj_path)
ready = obj.get_dbus_method('is_ready', interface_name)
ready(pid_, bin_path)
count += 1
print count
def publish_dbus():
loop = glib.MainLoop()
APP_Server()
loop.run()
if __name__ == '__main__':
gobject.threads_init()
dbus.glib.init_threads()
th1 = Thread(target = publish_dbus)
th1.start()
th2 = Thread(target = call_dbus)
th2.start()
sleep(10000000)
Then after run the server2.py, the application will terminated without finished all the dbus call in the thread "call_dbus".
And if I tried with the follwoing code, only changed the code in server2.py as the following:
FROM:
proxy_bus = dbus.SessionBus(private = True)
TO:
proxy_bus = dbus.SessionBus(private = True, mainloop = dbus.mainloop.NULL_MAIN_LOOP)
Now, there will have many connnections after the thread "callbus" finished by using the tools "d-feet" which can be used as a d-bus debugger to check if the dbus server is ready or if the dbus connection has been established.
If someone can make some suggeston to make it work normally??
What i've noticed is this:
Your bus/object names don't match.
You create a new dbus connection each time in your while loop. Very bad idea, specially seen that you don't close them.
Either move the call out of the loop, or use a shared connection (private=False)
You don't really need an own thread to publish the dbus object, that's what the mainloop is for anyway.
If you run a mainloop in a different thread, make sure you have a way to stop, otherwise kill will be the only way of terminating your program. Or put int in your main thread, then it should at least react to Ctrl-C
The sleep at the end of your program is unnecessary. As long as there are running non-daemon threads around the program won't exit anyway.
Putting all this together, this should work:
#!/usr/bin/python2.7
import dbus.service
import dbus.glib
import glib
import dbus.mainloop
import gobject
from dbus.mainloop.glib import DBusGMainLoop
from threading import Thread
from time import sleep
class APP_Server(dbus.service.Object):
def __init__(self):
bus = dbus.SessionBus(private = True, mainloop = DBusGMainLoop())
bus_name = dbus.service.BusName('de.test.app3', bus)
dbus.service.Object.__init__(self, bus_name, '/de/test/app3_obj_path')
#dbus.service.method("test.app3.interface",)
def is_ready(self):
return True
def call_dbus():
bus_name = 'de.test.app3'
obj_path = '/de/test/app3_obj_path'
interface_name = 'test.app3.interface'
proxy_bus = dbus.SessionBus(private = True)
count = 1
while count < 1000:
obj = None
try:
obj = proxy_bus.get_object(bus_name, obj_path)
except:
sleep(1)
obj = proxy_bus.get_object(bus_name, obj_path)
ready = obj.get_dbus_method('is_ready', interface_name)
#ready(pid_, bin_path)
count += 1
print count
if __name__ == '__main__':
gobject.threads_init()
dbus.glib.init_threads()
loop = glib.MainLoop()
server = APP_Server()
#th1 = Thread(target = publish_dbus)
#th1.start()
th2 = Thread(target = call_dbus)
th2.start()
loop.run()
I'm trying to build a PyQt app which (among other things) has the ability via a QTextEdit Box to function like a serial terminal program (HyperTerminal, TeraTerm, etc.) I've read through a few examples from the PySerial page and I think I've managed to get the receive data thread working properly but maybe not as efficiently as possible.
My problem is how do I take the last typed character in the QTextEdit box and send that out the serial connection? I've tried using the textChanged signal that QTextEdit emits, but that then sends everything that I type AND that it receives. I've tried setting up an eventFilter in my main GUI class, but I can't figure out how to get that over to the serial function in another file. Do I want to have a separate thread that listens for a signal emitted from the eventFilter? How do I do that? Is there a more elegant way to do this?
I'm sure I've just managed to overthink this and the solution is simple, but I'm somewhat struggling with it. I'll attach the relevant code snippets (not a full code set) and perhaps somebody can point me in the right direction. If anybody also thinks that the threading that I'm doing could be done in a more efficient manner, then please relay that to me as well!
Thanks for any help that anybody can provide!
Main File:
import sys
from PyQt4 import QtGui
from MainGUI import TestGUI
from SerialClasses import *
from SerialMiniterm import *
class StartMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(StartMainWindow, self).__init__(parent)
self.ui = TestGUI()
self.ui.setupUi(self)
self.ui.serialTextEditBox.installEventFilter(self)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.KeyPress and source is self.ui.serialTextEditBox):
# print some debug statements to console
if (event.key() == QtCore.Qt.Key_Tab):
print ('Tab pressed')
print ('key pressed: %s' % event.text())
print ('code pressed: %d' % event.key())
# do i emit a signal here? how do i catch it in thread?
self.emit(QtCore.SIGNAL('transmitSerialData(QString)'), event.key())
return True
return QtGui.QTextEdit.eventFilter(self, source, event)
def serialConnectCallback(self):
self.miniterm = SerialMiniterm(self.ui, self.SerialSettings)
self.miniterm.start()
temp = self.SerialSettings.Port + 1
self.ui.serialLabel.setText("<font color = green>Serial Terminal Connected on COM%d" % temp)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
app.setStyle("Cleanlooks")
myapp = StartMainWindow()
myapp.show()
sys.exit(app.exec_())
SerialMiniterm.py:
import serial
from PyQt4 import QtGui, QtCore
def character(b):
return b
class SerialMiniterm(object):
def __init__(self, ui, SerialSettings):
self.SerialSettings = SerialSettings
self.ui = ui
self.serial = serial.Serial(self.SerialSettings.Port, self.SerialSettings.BaudRate, parity=self.SerialSettings.Parity, rtscts=self.SerialSettings.RTS_CTS, xonxoff=self.SerialSettings.Xon_Xoff, timeout=1)
self.repr_mode = self.SerialSettings.RxMode
self.convert_outgoing = self.SerialSettings.NewlineMode
self.newline = NEWLINE_CONVERISON_MAP[self.convert_outgoing]
self.dtr_state = True
self.rts_state = True
self.break_state = False
def _start_reader(self):
"""Start reader thread"""
self._reader_alive = True
self.receiver_thread = ReaderThread(self.alive, self._reader_alive, self.repr_mode, self.convert_outgoing, self.serial)
self.receiver_thread.connect(self.receiver_thread, QtCore.SIGNAL("updateSerialTextBox(QString)"), self.updateTextBox)
self.receiver_thread.start()
def _stop_reader(self):
"""Stop reader thread only, wait for clean exit of thread"""
self._reader_alive = False
self.receiver_thread.join()
def updateTextBox(self, q):
self.ui.serialTextEditBox.insertPlainText(q)
self.ui.serialTextEditBox.moveCursor(QtGui.QTextCursor.End)
#print "got here with value %s..." % q
def start(self):
self.alive = True
self._start_reader()
# how do i handle transmitter thread?
def stop(self):
self.alive = False
def join(self, transmit_only=False):
self.transmitter_thread.join()
if not transmit_only:
self.receiver_thread.join()
class ReaderThread(QtCore.QThread):
def __init__(self, alive, _reader_alive, repr_mode, convert_outgoing, serial, parent=None):
QtCore.QThread.__init__(self, parent)
self.alive = alive
self._reader_alive = _reader_alive
self.repr_mode = repr_mode
self.convert_outgoing = convert_outgoing
self.serial = serial
def __del__(self):
self.wait()
def run(self):
"""loop and copy serial->console"""
while self.alive and self._reader_alive:
data = self.serial.read(self.serial.inWaiting())
if data: #check if not timeout
q = data
self.emit(QtCore.SIGNAL('updateSerialTextBox(QString)'), q)
Something like this?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class Terminal(QtGui.QPlainTextEdit):
def keyPressEvent(self, event):
print event.text()
return QtGui.QPlainTextEdit.keyPressEvent(self, event)
term = Terminal()
term.show()