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()
Related
i need a scheduler in a Textual application to periodically query an external data source. As a test i've tried to use APscheduler to call a tick() function every second.
However nothing happens although the scheduler should be started.
What is going on and how to debug this?
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.widgets import *
from apscheduler.schedulers.background import BackgroundScheduler
class HeaderApp(App):
def __init__(self, *args, **kwargs):
self.sched = BackgroundScheduler()
self.sched.add_job(self.tick,'interval', seconds=1)
self.sched.start()
super(HeaderApp, self).__init__(*args, **kwargs)
def compose(self) -> ComposeResult:
yield Header()
yield TextLog()
def tick(self):
text_log = self.query_one(TextLog)
text_log.write("tick")
def on_mount(self):
text_log = self.query_one(TextLog)
text_log.write(self.sched.running)
if __name__ == "__main__":
app = HeaderApp()
app.run()
I'm not familiar with apscheduler, but since you haven't had a response, could you use the builtin set_interval which will call a method at regular intervals?
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.widgets import *
class HeaderApp(App):
def compose(self) -> ComposeResult:
yield Header()
yield TextLog()
def tick(self):
text_log = self.query_one(TextLog)
text_log.write("tick")
def on_mount(self):
self.set_interval(1, self.tick)
if __name__ == "__main__":
app = HeaderApp()
app.run()
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()
This question already has an answer here:
PyQt5 - QThread: Destroyed while thread is still running
(1 answer)
Closed 1 year ago.
I working on software, that includes parts working with the WHO ICD11 API.
When I run the code:
import json
import re
import threading
import time
from typing import Dict, List
import qdarkgraystyle as qdarkgraystyle
import requests
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QTreeView
from threading import Lock
from gui import Ui_MainWindow
import auth
printlock = Lock()
p = print
def print(*a, **b):
with printlock:
p(*a, **b)
class g:
max = 1
progress = 0
end_workers = False
loaded_dict = None
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super(ApplicationWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def linearization_url():
return f"https://id.who.int/icd/release/{ui.dropRevision.currentText().split('/')[0]}/{ui.dropRelease.currentText()}{('/' + ui.dropRevision.currentText().split('/')[1]) if len(ui.dropRevision.currentText().split('/')) > 1 else ''}"
def download():
loader = Loader(linearization_url())
loader.statusUpdateHook.connect(updatehook)
loader.statusFinished.connect(finishedLoader)
loader.start()
def updatehook():
ui.progress.setTextVisible(True)
ui.progress.setMaximum(gl.max)
ui.progress.setValue(gl.progress)
def finishedLoader():
json.dump(gl.loaded_dict, open("dict.json"), indent=4)
def split_link(url: str) -> Dict[str, str]:
return re.search(
"https?://id.who.int/icd/release/(?P<revision>[0-9]{2})/(?P<release>[^/]*)(/(?P<linearization>.*))?",
url).groupdict()
def worker(loader):
print("Worker booting...")
_token = gl.token
over = True
while not gl.end_workers:
url = ""
with loader.index_lock:
try:
url = loader.working_list[loader.index]
loader.index += 1
except IndexError:
over = False
if over:
json = request_json(url, _token)
with loader.finished_count_lock:
loader.working_dict[url] = json
if "child" in json:
for child in json["child"]:
loader.working_list.append(child)
loader.finished_count += 1
else:
over = True
def loadReleases():
token = getToken(auth.id, auth.secret)
ui.dropRelease.clear()
ui.dropRelease.repaint()
for release in request_json("https://id.who.int/icd/release/" + ui.dropRevision.currentText(), token)[
"release"]:
ui.dropRelease.addItem(split_link(release)["release"])
def getToken(clientID, clientSecret) -> str:
return requests.post('https://icdaccessmanagement.who.int/connect/token',
data={'client_id': clientID, 'client_secret': clientSecret, 'scope': 'icdapi_access',
'grant_type': 'client_credentials'}).json()['access_token']
def request_json(link_: str, token_: str):
headers_ = {
'Authorization': 'Bearer ' + token_,
'Accept': 'application/json',
'Accept-Language': 'en',
'API-Version': 'v2'
}
return requests.get(link_, headers=headers_).json()
class Loader(QtCore.QThread):
statusFinished = QtCore.pyqtSignal()
statusUpdateHook = QtCore.pyqtSignal()
index = 0
finished_count = 0
working_list = []
working_dict = {}
index_lock = Lock()
finished_count_lock = Lock()
workers = []
def __init__(self, lurl: str):
super().__init__()
self.working_list.append(lurl)
def progressUpdate(self):
gl.max = len(self.working_list)
gl.progress = self.finished_count
self.statusUpdateHook.emit()
def run(self):
for i in range(0, 20):
self.workers.append(threading.Thread(target=worker, args=(self,)))
self.workers[i].start()
while self.finished_count < len(self.working_list):
with self.index_lock:
with self.finished_count_lock:
self.progressUpdate()
time.sleep(5)
for work in self.workers:
if work.isAlive():
gl.end_workers = True
gl.loaded_dict = self.working_dict
self.statusFinished.emit()
if __name__ == "__main__":
import sys
gl = g()
gl.token = getToken(auth.id, auth.secret)
tabs: List[QTreeView] = []
app = QtWidgets.QApplication(sys.argv)
application = ApplicationWindow()
application.setStyleSheet(qdarkgraystyle.load_stylesheet())
ui = application.ui
ui.buttonDownload.clicked.connect(download)
ui.dropRevision.addItems(["10", "11/mms"])
ui.dropRevision.currentIndexChanged.connect(loadReleases)
loadReleases()
application.show()
sys.exit(app.exec_())
in Pycharms debug mode, it does, what I want it to. It works fine as long as it is in debug mode, while when in normal mode, when the buttonDownload.clicked event is triggered, the whole program crashes with the only output being:
QThread: Destroyed while thread is still running
Has anyone any idea on how to fix that?
(For reproducing purposes: You need API keys to access the API. They are imported from auth as auth.id and auth.secret. ID and secret can be obtained from an account over the WHO ICD11 API site)
Loader inherits QThread, in download function QThread object is bound to local variable loader, on exiting function this variable got garbage collected and bound object gets destroyed. You need to make sure loader variable outlive function, for example make it global variable or return it from function and store somewhere.
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
I'm trying to change the state of a Gtk status icon from a thread as specified in MailThread.run() below, but I don't know how to reach the status icon object from the method in order to change set_visible to either True or False.
Basically I would like to know what to write in place of "# set status icon visible off/on".
#!/usr/bin/env python
import gtk, sys, pynotify, imaplib, time, threading
from email import parser
class Mail:
def check_mail(self):
obj = imaplib.IMAP4_SSL('imap.gmail.com','993')
acc = 'email'
pwrd = 'pass'
obj.login(acc, pwrd)
obj.select()
num = str(len(obj.search(None,'UnSeen')[1][0].split()))
return acc, num
class MailThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
gtk.gdk.threads_init()
def run(self):
while True:
print "hello"
mail = Mail()
num = mail.check_mail()[1]
if num < 1:
# set status icon visible off
else:
# set status icon visible on
time.sleep(60)
class StatusIcon:
# activate callback
def activate( self, widget, data=None):
mail = Mail()
acc, num = mail.check_mail()
pynotify.init("myapp")
n = pynotify.Notification(acc, "You have " + num + " unread e-mails.", "emblem-mail")
n.show()
# Show_Hide callback
def show_hide(self, widget,response_id, data= None):
if response_id == gtk.RESPONSE_YES:
widget.hide()
else:
widget.hide()
# destroyer callback
def destroyer(self, widget,response_id, data= None):
if response_id == gtk.RESPONSE_OK:
gtk.main_quit()
else:
widget.hide()
# popup callback
def popup(self, button, widget, data=None):
dialog = gtk.MessageDialog(
parent = None,
flags = gtk.DIALOG_DESTROY_WITH_PARENT,
type = gtk.MESSAGE_INFO,
buttons = gtk.BUTTONS_OK_CANCEL,
message_format = "Do you want to close e-mail notifications?")
dialog.set_title('Exit')
dialog.connect('response', self.destroyer)
dialog.show()
def __init__(self):
# create a new Status Icon
self.staticon = gtk.StatusIcon()
self.staticon.set_from_icon_name("emblem-mail")
self.staticon.connect("activate", self.activate)
self.staticon.connect("popup_menu", self.popup)
self.staticon.set_visible(True)
# starting thread
thread = MailThread()
thread.setDaemon(True)
thread.start()
# invoking the main()
gtk.main()
if __name__ == "__main__":
# status icon
statusicon = StatusIcon()
You can accept the status icon in the thread's __init__():
class MailThread(threading.Thread):
def __init__(self, status_icon = None):
threading.Thread.__init__(self)
gtk.gdk.threads_init()
self.status_icon = status_icon
And then you can use it in run().
Additionally, you need to do all the GUI work from the main thread. The main thread has a queue maintained by GTK you can use to tell it to go do some GUI work. This is how it works:
def run(self):
# <...>
if num < 1:
gobject.idle_add(self.set_status_icon, False)
else:
gobject.idle_add(self.set_status_icon, True)
# <...>
def set_status_icon(self, state = False):
# code that changes icon state goes here
pass
idle_add basically means "add that to the queue and do it when you have some free time".