I'm coding a Texteditor class:
from threading import *
class Editor(Thread):
{python code}
if __name__ == "__main__":
editor = Editor()
editor.start()
I want this editor Thread to run as daemon. How can I do this?
I've tried:
editor = Editor(daemon=True)
editor.daemon = True
self.daemon = True
Greetings,
Dave
Like the below
from threading import *
class Editor(Thread):
def __init__(self, is_daemon: bool):
super(Editor, self).__init__(daemon=is_daemon)
def run(self):
print('in run')
if __name__ == "__main__":
editor = Editor(True)
print(editor.daemon)
editor.start()
Related
I was trying to pause/resume a task using hotkey, wrote the program bellow which is working fine while hitting Pause hotkey, but resume is not working. I guess I did some logical errors and need your expert advice to overcome that. Here is the script I wrote
import keyboard
class Test:
def __init__(self):
self.run = True
keyboard.add_hotkey("ctrl+alt+p", self.set_run)
keyboard.add_hotkey("ctrl+alt+r", self.set_run_r)
def set_run(self):
self.run = False
def set_run_r(self):
self.run = True
def start(self):
val = 1
while self.run:
val += 1
print("running ", val)
keyboard.wait("esc")
Test().start()
Try this
import keyboard
import sys
class Test:
def __init__(self):
self.val=1
self.run = True
keyboard.add_hotkey("ctrl+alt+p", self.set_run)
keyboard.add_hotkey("ctrl+alt+r", self.set_run_r)
def set_run(self):
self.run = False
def set_run_r(self):
self.run = True
def start(self):
self.val += 1
print(self.val)
return
test= Test()
try:
while True:
if test.run:
test.start()
else:
pass
except KeyboardInterrupt:
sys.exit()
Here's my simple example code:
# -*- coding: utf-8 -*-
import multiprocessing
import time
def some_function():
return "hello!"
def get_address_type(address):
return 'tcp'
class PseudoThing():
def __init__(self, address):
self.address = address
self.server = None
def attach(self):
if get_address_type(self.address) == 'tcp':
ip, port = self.address.split(':', 1)
self.server = some_function()
else:
self.server = some_function()
def worker(self):
print("in worker!")
for i in range(10):
print("I'm a worker doing worker things...")
self.attach()
if self.server:
return True
time.sleep(0.2)
def parent(self):
print("I'm a parent doing parent things!")
def start_process(self):
p = multiprocessing.Process(target=self.worker)
print("starting process")
p.start()
return p
def main():
nvr = PseudoThing("kitty")
p = nvr.start_process()
p.join()
print("__name__ = {}".format(__name__))
if __name__ == "__main__":
print("doing main!")
main()
However, nothing is getting printed out from worker, as I would expect. Instead, this is the output of the program:
__name__ = __main__
doing main!
starting process
I am suspecting this has something to do with the class structure (I recall having issues with this on Python 2), but I am not entirely sure. Where can I add more print statements to figure what's going on? Where are things going wrong?
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'm trying to display the time in a FixedText widget in an NPSAppManaged application.
So far I've got this:
import npyscreen
import datetime
import threading
from time import sleep
class MainForm(npyscreen.Form):
def create(self):
self.add(npyscreen.FixedText, value = "Time")
def afterEditing(self):
self.parentApp.setNextForm(None)
def set_value(self):
return "Tom"
class TestApp(npyscreen.NPSAppManaged):
def onStart(self):
self.registerForm("MAIN", MainForm())
thread_time = threading.Thread(target=self.update_time,args=())
thread_time.daemon = True
thread_time.start()
def update_time(self):
while True:
# self.f.wStatus2.value = datetime.datetime.now().ctime()
# self.f.wStatus2.display()
sleep(1)
if __name__ == "__main__":
App = TestApp()
App.run()
I'm just not sure how to reference the .value parameter for the widget from the thread and update it. What should I be doing?
You need to assign the npyscreen.FixedText to a variable as such:
def create(self):
self.w_time = self.add(npyscreen.FixedText, value = "Time")
Now you can use self.w_time.value to access it.
import npyscreen
import datetime
import threading
from time import sleep
class MainForm(npyscreen.Form):
def create(self):
self.date = self.add(npyscreen.TitleText, value = str(datetime.datetime.now()), editable=False, name='Something')
def afterEditing(self):
self.parentApp.setNextForm(None)
def set_value(self):
return "Tom"
class TestApp(npyscreen.NPSAppManaged):
def onStart(self):
self.textual = MainForm()
self.registerForm("MAIN", self.textual)
thread_time = threading.Thread(target=self.update_time,args=())
thread_time.daemon = True
thread_time.start()
def update_time(self):
while True:
self.textual.date.value = str(datetime.datetime.now())
self.textual.display()
sleep(1)
if __name__ == "__main__":
App = TestApp()
App.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()