Calling a thread within a module in python - python

I have a log in screen which calls a module from a file which is 'HomescreenscrollCopy31' . This works perfectly fine.
The only issue is that there is a thread within the module which does not seem to operate.
Here is the code in the login screen:
def login():
content = nameentry.get()
content1 = IDentry.get()
if content == "1" and content1 == "1":
root.destroy()
from HomescreenscrollCopy31 import FullScreenApp
The HomescreenscrollCopy31.py file looks like this,
class FullScreenApp(object):
def __init__(self, master, **kwargs):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry("{0}x{1}+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.bind('<Escape>',self.toggle_geom)
def toggle_geom(self,event):
geom=self.master.winfo_geometry()
print(geom,self._geom)
self.master.geometry(self._geom)
self._geom=geom
def trick(threadName, sleepTime):
while 1 < 2:
.....
try:
t = threading.Thread(target=trick, args=("Trick running", 5))
t.daemon = True
t.start()
except: Exception,
print "start up"
It seems that it runs through the HomescreenscrollCopy31.py and politely prints the "start up" only to tease me, as it never actually runs the thread and thus should print the "Trick running" output.
Why is this?

I think it's better to write it this way.
def login():
content = nameentry.get()
content1 = IDentry.get()
if content == "1" and content1 == "1":
root.destroy()
from HomescreenscrollCopy31 import FullScreenApp
myFullScreenApp = FullScreenApp(...) # you need to give it some input, like master, to initialize an instance for FullScreenApp class
class FullScreenApp(object):
def __init__(self, master, **kwargs):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry("{0}x{1}+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.bind('<Escape>',self.toggle_geom)
# these code will be executed when instance initializing
t = threading.Thread(target=self.trick, args=["Trick running", 5])
t.daemon = True
t.start()
def toggle_geom(self,event):
geom=self.master.winfo_geometry()
print(geom,self._geom)
self.master.geometry(self._geom)
self._geom=geom
def trick(threadName, sleepTime):
while 1 < 2:
.....
You just need to initialize an instance of the class to get thread
running. If using staticmethod way, it will make code more
complicated which I don't recommend.
When invoking a new thread, args should be a list([]) but not a
tuple(()).
You can use while 1 instead of while 1<2. Anyway, this is not the
major issue. :)
Hope it helps.

Related

FastAPI and "While True" process

I have some function that is doing stuff in while True (for example just print a str):
class LoopHandler(metaclass=Singleton):
def start_loop(self, phrase: str):
while True:
print(phrase)
time.sleep(1)
And I have a simple FastAPI server running in parallel:
class APIServer(uvicorn.Server):
def install_signal_handlers(self):
pass
#contextlib.contextmanager
def run_in_thread(self):
thread = threading.Thread(target=self.run)
thread.start()
try:
while not self.started:
time.sleep(1e-3)
yield
except KeyboardInterrupt:
self.should_exit = True
thread.join()
And it works fine, text prints, API works.
But the task is to "restart" loop when specific API method is called. Something like this:
#app.get("/get")
async def get():
response = {'response': 'response'}
# restart loop here with LoopHandler().start_loop('another Text')
return response
Thanks for any advice!
My main():
if __name__ == '__main__':
config = uvicorn.Config("api_view:app", log_level="debug")
server = APIServer(config=config)
with server.run_in_thread():
LoopHandler().start_loop('Text')
ADD:
When I call LoopHandler from API, It begin new thread and new LoopHandler instance in it. So, if I add flag, like this:
class LoopHandler(metaclass=Singleton):
def __init__(self, done: bool = False):
self.done = done
def start_loop(self, phrase: str):
while not self.done:
print(phrase)
time.sleep(1)
My console looks like this:
Text
another Text
Text
another Text
Text

Why is the main thread of my multithreaded application unresponsive to Ctrl+C?

I have written a multithreaded application to watch and respond to changes in given list of files. I have a Watch class which gets the file size and sets it to size variable upon first call. Then, after a few seconds it again gets the size of the file and compares it with with the previous size and, if changed, sets size to the current size of the file. Furthermore there is a WatchWorker class which is a subclass of threading.Thread. The WatchWorker which makes use of Watch class to 'watch ' a given file.
Now here is the real problem :
The code I have written is working and notifies the user when a change is detected. But there is no response when I try to quit from the application using Ctrl+C. I'm on Windows.
Code:
import time
import threading
import os
class Watch(object):
def __init__(self, path, time=5):
self.path = path
self.time = time
self.size = os.stat(path).st_size
def loop(self):
while True:
time.sleep(self.time)
size = os.stat(self.path).st_size
if size != self.size:
self.size = size
print "Change detected in file {}".format(self.path)
class Watch_Worker(threading.Thread):
def __init__(self, path, *args, **kwargs):
super(Watch_Worker, self).__init__(*args, **kwargs)
self.path = path
def run(self):
super(Watch_Worker, self).run()
Watch(self.path).loop()
def main(*args):
for i in args:
thrd = Watch_Worker(path=i)
thrd.start()
print 'Watching ' + i
print "From main thread"
if __name__ == '__main__':
main('blah.js', 'cs.c', 'ab.rb')
Edit
Modified code to compare the values produced os.stat('somefile.ext').st_size).
I solved the problem of the main thread being prevented from exiting by setting self.daemon = True. The main thread does not wait for the threads to exit. This is solved by adding a infinite while loop withtime.sleep(5) to the end of main function. Here is the code:
class Watch_Worker(threading.Thread):
def __init__(self, path, time=2, *args, **kwargs):
super(Watch_Worker, self).__init__(*args, **kwargs)
self.path = path
self.time = time
self.size = os.stat(path).st_size
self.daemon = True
def run(self):
super(Watch_Worker, self).run()
while True:
time.sleep(self.time)
size = os.stat(self.path).st_size
if size != self.size:
self.size = size
print "Change detected in file {}".format(self.path)
def main(*args):
for i in args:
thrd = Watch_Worker(path=i)
thrd.start()
print 'Watching ' + i
while True:
time.sleep(5)
if __name__ == '__main__':
main('blah.js', 'cs.c', 'ab.rb')

How to make this code work well with Queue?

I have a little doubt if one could solve my issue, and create successful communication between threads.
First example and this is how it should be working, but does not work well:
import Queue,threading,time
class th(threading.Thread):
def __init__(self,q):
threading.Thread.__init__(self)
self.q = q
self.t = time
def run(self):
for i in range(5):
self.q.put(i)
self.t.sleep(0.5) # <----------
self.q.put('end')
class main(object):
def __init__(self):
self.q = Queue.Queue()
self.thread = th(self.q)
self.thread.setDaemon(True)
self.thread.run()
self.call()
def call(self):
while True:
recv = self.q.get();
if recv == 'end':
break
else:
print recv
if __name__ == '__main__':
root = main()
root.call()
In this example, all printed at the same time:
0,1,2,3,4
Second example:
import Queue,threading,time
class th(threading.Thread):
def __init__(self,q):
threading.Thread.__init__(self);
self.q = q
self.t = time
def run(self):
for i in range(5):
self.q.put(i) # <------ no sleep()
self.q.put('end')
class main(object):
def __init__(self):
self.q = Queue.Queue()
self.thread = th(self.q)
self.thread.setDaemon(True)
self.thread.run()
self.call()
def call(self):
while True:
recv = self.q.get()
if recv == 'end':
break
else:
print recv
if __name__ == '__main__':
root = main()
root.call()
the code is printed as it has to
0,
1
2
3
4
one to one
is there any way that the sleep function in the same way?
You don't want to call the run method on a thread directly. Call start instead, which will kick off the child thread, which will in turn run the run method.
Your current code is essentially single threaded, since the run call does the work of the child thread in the parent instead. The child thread is never actually started! (You're also calling your main.call method twice, which I'd expect to block or raise an exception, but that's a separate issue.)
sorry, it was something very simple, really simple, just had to replace
self.thread.run()
by
self.threat.start()

Sub Process in its own Thread

I'm wondering if the following class is sound. I'm using it to launch a bunch of simulators for each test in my test environment.
class SubProcessInOwnThread(threading.Thread):
def __init__(self, arguments, currentWorkingDirectory):
self.arguments = arguments
self.currentWorkingDirectory = currentWorkingDirectory
threading.Thread.__init__(self)
self.isTerminated = False
def run(self):
try:
self.subProcess = subprocess.Popen(self.arguments, cwd=self.currentWorkingDirectory)
self.subProcess.wait()
finally:
self.isTerminated = True
def kill(self):
while not self.isTerminated:
try:
self.subProcess.kill()
except:
time.sleep(0.1)
Some senarios:
# Normal
subProcessThreadArguments = ["cmd.exe"]
subProcessThread = SubProcessInOwnThread(subProcessThreadArguments,r"C:\\")
subProcessThread.start()
time.sleep(5)
subProcessThread.kill()
# Process killed very quickly
subProcessThreadArguments = ["cmd.exe"]
subProcessThread = SubProcessInOwnThread(subProcessThreadArguments,r"C:\\")
subProcessThread.start()
subProcessThread.kill()
# Incorrect configuration
subProcessThreadArguments = ["cmdsfgfg.exe"]
subProcessThread = SubProcessInOwnThread(subProcessThreadArguments,r"C:\\")
subProcessThread.start()
time.sleep(5)
subProcessThread.kill()
So I can create simulators like this:
subProcessThreadArguments1 = ["sim1.exe"]
subProcessThread1 = SubProcessInOwnThread(subProcessThreadArguments1,r"C:\\")
subProcessThread1.start()
subProcessThreadArguments2 = ["sim2.exe"]
subProcessThread2 = SubProcessInOwnThread(subProcessThreadArguments2,r"C:\\")
subProcessThread2.start()
# do test...
subProcessThread1.kill()
subProcessThread2.kill()
I'd be interested in any improvents. Should I consider the use of the with keyword? If so, what would the benifits be?
Thanks!
I don't see the point of having a separate thread being stuck in wait() here. Working directly on the subprocess would work like
class SubProcessWithoutThread(object):
def __init__(self, arguments, currentWorkingDirectory):
self.arguments = arguments
self.currentWorkingDirectory = currentWorkingDirectory
self.isTerminated = False
def start(self):
self.subProcess = subprocess.Popen(self.arguments, cwd=self.currentWorkingDirectory)
def kill(self):
while self.subProcess.poll() is None:
try:
self.subProcess.kill()
except:
time.sleep(0.1)
__enter__ = start
def __exit__(self, *x):
self.kill()
(untested)
I have added the methods for a context manager, but I cannot see how that would help you as it would be quite a bunch of with statements which you would have to create, including the necessary indentation.
But maybe I have got your intention wrong...

Simple pygtk and threads example please

Can someone give me a simple example involving threads in this manner, please.
Problem with my code is that when I click button One, GUI freezes until its finished. I want buttons to stay responsive when def is being executed. How can i fix that?
class fun:
wTree = None
def __init__( self ):
self.wTree = gtk.glade.XML( "ui.glade" )
dic = {
"on_buttonOne" : self.one,
"on_buttonTwo" : self.two,
}
self.wTree.signal_autoconnect( dic )
gtk.main()
def sone(self, widget):
time.sleep(1)
print "1"
time.sleep(1)
print "2"
time.sleep(1)
print "3"
def stwo(self, widget):
time.sleep(1)
print "4"
time.sleep(1)
print "5"
time.sleep(1)
print "6"
do=fun()
Pretty please, help me.
Use Python Threads: http://docs.python.org/library/threading.html
Something like:
class SoneThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.start() # invoke the run method
def run(self):
time.sleep(1)
print "1"
time.sleep(1)
print "2"
time.sleep(1)
print "3"
Now in sone just call SoneThread(), that should work.
Also you need to call gtk.gdk.threads_init() in order to make python threads work with your GTK+ application.
See: http://library.gnome.org/devel/pygtk/stable/gdk-functions.html#function-gdk--threads-init
When using gtk, it will run a main loop, and you schedule everything you want to do as events to the gtk loop. You don't need threads to do anything.
Here's a complete, full, ready-to-run example that uses glib.timeout_add to do what you want.
Note that clicking on both buttons (or multiple times on a button) doesn't freeze the gui and everything happens "at the same time"...
import gtk
import glib
def yieldsleep(func):
def start(*args, **kwds):
iterable = func(*args, **kwds)
def step(*args, **kwds):
try:
time = next(iterable)
glib.timeout_add_seconds(time, step)
except StopIteration:
pass
glib.idle_add(step)
return start
class Fun(object):
def __init__(self):
window = gtk.Window()
vbox = gtk.VBox()
btnone = gtk.Button('one')
btnone.connect('clicked', self.click_one)
btnone.show()
vbox.pack_start(btnone)
btntwo = gtk.Button('two')
btntwo.connect('clicked', self.click_two)
btntwo.show()
vbox.pack_start(btntwo)
vbox.show()
window.add(vbox)
window.show()
#yieldsleep
def click_one(self, widget, data=None):
yield 1 #time.sleep(1)
print '1'
yield 1 #time.sleep(1)
print '2'
yield 1 #time.sleep(1)
print '3'
#yieldsleep
def click_two(self, widget, data=None):
yield 1 #time.sleep(1)
print '4'
yield 1 #time.sleep(1)
print '5'
yield 1 #time.sleep(1)
print '6'
do = Fun()
gtk.main()

Categories

Resources