Daemon thread not exiting despite main program finishing - python

I've already referred to this thread, but it seems to be outdated
and there doesn't seem to be a clean explanation
Python daemon thread does not exit when parent thread exits
I'm running python 3.6 and trying to run the script from either IDLE or Spyder IDE.
Here is my code:
import threading
import time
total = 4
def creates_items():
global total
for i in range(10):
time.sleep(2)
print('added item')
total += 1
print('creation is done')
def creates_items_2():
global total
for i in range(7):
time.sleep(1)
print('added item')
total += 1
print('creation is done')
def limits_items():
#print('finished sleeping')
global total
while True:
if total > 5:
print ('overload')
total -= 3
print('subtracted 3')
else:
time.sleep(1)
print('waiting')
limitor = threading.Thread(target = limits_items, daemon = True)
creator1 = threading.Thread(target = creates_items)
creator2 = threading.Thread(target = creates_items_2)
print(limitor.isDaemon())
creator1.start()
creator2.start()
limitor.start()
creator1.join()
creator2.join()
print('our ending value of total is' , total)
limitor thread doesn't seem to be ending despite being a daemon thread.
Is this a way to get this working from IDLE or Spyder?
Thanks.

I had the same Problem and solved it by using multiprocessing instead of threading:
from multiprocessing import Process
import multiprocessing
from time import sleep
def daemon_thread():
for _ in range(10):
sleep(1)
print("Daemon")
if __name__ == '__main__':
multiprocessing.freeze_support()
sub_process = Process(target = daemon_thread, daemon = True)
sub_process.start()
print("Exiting Main")
I haven't yet really understood why I need the call to freeze_support() but it makes the code work.

Related

get results of terminated map_async of multiprocessing

I am running a script with multiprocessing map_async. what I need to do is to get the uncomplete result of AsyncResult object (assuming it already finished calculating some of the cases given) after terminating Pool with terminate(). using get() would just hang the script, how can I do this?
I know this can be done with apply_sync with some manipulation, but can it be done somehow with map_async?
working example of the situation:
import multiprocessing
import time
def example_run(i):
time.sleep(0.7)
return i
if __name__ == '__main__':
terminate = False
pool = multiprocessing.Pool(10)
result_async = pool.map_async(example_run,range(100))
i = 0
while True:
time.sleep(1.0)
if i == 70:
terminate = True
print(result_async.ready(),terminate)
if result_async.ready():
break
elif terminate:
pool.terminate()
break
i += 10
result = result_async.get() # The problem is here, it will just wait
print(result)
pool.close()
pool.join()
I found a solution to the problem; with some digging, AsyncResult._value seem to hold the values of the execution, with None in case it is not evaluated yet
import multiprocessing
import time
def example_run(i):
time.sleep(0.7)
return i
if __name__ == '__main__':
terminate = False
pool = multiprocessing.Pool(10)
result_async = pool.map_async(example_run,range(100))
i = 0
while True:
time.sleep(1.0)
if i == 70:
terminate = True
print(result_async.ready(),terminate)
if result_async.ready():
break
elif terminate:
pool.terminate()
break
i += 10
result = []
for value in result_async._value:
if value is not None:
result.append(value)
else:
result.append("failed")
print(result)
pool.close()
pool.join()

Threading infinity loops and sync problem

I am getting headache, trying to figure out how to deal with 2 threads in Python.
My Idea was to create one thread for blinking LEDs, that have infinite while loop, and when global variable changes to True,it starts to blink etc, but it is always in infinite loop.
other main thread, will be waiting for signal to blink, but also if the signal is while blinking, it will reset global blinking timer, so it has to be in separate thread.
Problem I am having, when I start LEDs thread from main thread, because LED thread has infinite loop, it stops main thread from running any further than flashThread.start()
if __name__ == "__main__":
print('starting main...')
flashThread = threading.Thread(name='SFlashing', daemon = True, target=Flash)
flashThread.start()
while(True):
print('running main...')
time.sleep(2)
it never gets to running main...
Flash() is just infinite while loop and depending on global variables it does stuff...
Here is an example of a main thread printing running main... + a parallel thread incrementing a variable count, based on your explanations. Your code should work, maybe could you give us more information about the Flash loop so we can help you ?
import threading
import time
def Flash():
count = 0
while True:
print("count", count)
count += 1
time.sleep(1)
print('starting main...')
flashThread = threading.Thread(name='SFlashing', daemon = True, target=Flash)
flashThread.start()
while(True):
print('running main...')
time.sleep(2)
Output:
starting main...
count 0
running main...
count 1
running main...
count 2
count 3
running main...
** EDIT **
Here there is no more time.sleep()in Flash, until the global variable totois changed in the main loop.
import threading
import time
global toto
toto = 0
def Flash():
global toto
count = 0
while True:
print("count", count)
count += 1
if toto == 2:
print("YEEHA")
time.sleep(2)
print('starting main...')
flashThread = threading.Thread(name='SFlashing', daemon = True, target=Flash)
flashThread.start()
while(True):
print('running main...')
time.sleep(1)
toto = 2

Small Example for pyserial using Threading

Can anyone please give me a small and simple example on how to use threading with pyserial communication.
I am googling for over three days and I am still illeterate and I dont even have a working piece of code which integrate both of them
Basically I am aiming to use threading in this scenario:
Have a serial communication continuously go on in the back ground to attain certain value (say A) from an MCU.
Stop attaining value A - then attain value B...and start continuously attaining value A again.
You can find some basic code here.
import threading
import time
import sys
import serial
import os
import time
def Task1(ser):
while 1:
print "Inside Thread 1"
ser.write('\x5A\x03\x02\x02\x02\x09') # Byte ArrayTo Control a MicroProcessing Unit
b = ser.read(7)
print b.encode('hex')
print "Thread 1 still going on"
time.sleep(1)
def Task2(ser):
print "Inside Thread 2"
print "I stopped Task 1 to start and execute Thread 2"
ser.write('x5A\x03\x02\x08\x02\x0F')
c = ser.read(7)
print c.encode('hex')
print "Thread 2 complete"
def Main():
ser = serial.Serial(3, 11520)
t1 = threading.Thread(target = Task1, args=[ser])
t2 = threading.Thread(target = Task2, args=[ser])
print "Starting Thread 1"
t1.start()
print "Starting Thread 2"
t2.start()
print "=== exiting ==="
ser.close()
if __name__ == '__main__':
Main()
There's no factual basis for the claim by Task2:
print "I stopped Task 1 to start and execute Thread 2"
Your implementation starts one thread then immediately starts the other without stopping the first. This means that the ser.read and ser.write commands could interfere with each other.
The simplest thing you could do to address this is to introduce variables that allow communication:
import sys
import os
import time
import threading
thread_flag = None
def Report(s):
print s
sys.stdout.flush() # helps to ensure messages from different threads appear in the right order
def Stop():
global thread_flag
thread_flag = 'stop'
def Task1(ser):
Report("Inside Thread 1")
global thread_flag
thread_flag = 'go'
while True:
Report("Thread 1 waiting for permission to read")
while thread_flag != 'go': time.sleep( 0.001 )
while thread_flag == 'go':
Report("Thread 1 is reading")
#ser.write('\x5A\x03\x02\x02\x02\x09') # Byte ArrayTo Control a MicroProcessing Unit
#b = ser.read(7)
#Report(b.encode('hex'))
time.sleep(1)
if thread_flag == 'stop': break
else: thread_flag = 'paused' # signals that the inner loop is done
Report("Thread 1 complete")
def Task2(ser):
Report("Inside Thread 2")
global thread_flag
thread_flag = 'pause' # signals Task1 to pause
while thread_flag != 'paused': time.sleep(0.001) # waits for Task1 inner loop to exit
Report("I stopped Task 1 to start and execute Thread 2")
#ser.write('x5A\x03\x02\x08\x02\x0F')
#c = ser.read(7)
#Report(c.encode('hex'))
thread_flag = 'go' # signals Thread 1 to resume
Report("Thread 2 complete")
def Main():
ser = None # serial.Serial(3, 11520)
t1 = threading.Thread(target = Task1, args=[ser])
t2 = threading.Thread(target = Task2, args=[ser])
Report("Starting Thread 1")
t1.start()
time.sleep(3)
Report("Starting Thread 2")
t2.start()
if __name__ == '__main__':
Main()
That approach uses a global variable, which is often frowned upon. You could instead make Task1 and Task2 methods of an object self that carries both self.ser and self.thread_flag as attributes.
For any inter-thread communication more complex than this, you need to investigate locks, mutexes and semaphores (e.g. threading.Lock)

Is there a way to stop a Python thread when the correct answer is found?

I'm trying to check a list of answers like so:
def checkAns(File, answer):
answer = bytes(answer, "UTF-8")
try:
File.extractall(pwd=answer)
except:
pass
else:
print("[+] Correct Answer: " + answer.decode("UTF-8") + "\n")
def main():
File = zipfile.ZipFile("questions.zip")
ansFile = open("answers.txt")
for line in ansFile.readlines():
answer = line.strip("\n")
t = Thread(target=extractFile, args=(File, answer))
t.start()
Assume the correct answer is 4 and your list contains values 1 through 1000000.
How do I get it to stop after it gets to 4 and not run through the remaining numbers in the list?
I have tried it several different ways:
else:
print("[+] Correct Answer: " + answer.decode("UTF-8") + "\n")
exit(0)
and also
try:
File.extractall(pwd=answer)
print("[+] Correct Answer: " + answer.decode("UTF-8") + "\n")
exit(0)
except:
pass
How do I get all the threads to stop after the correct answer is found?
Strangely in Python you can't kill threads:
Python’s Thread class supports a subset of the behavior of Java’s
Thread class; currently, there are no priorities, no thread groups,
and threads cannot be destroyed, stopped, suspended, resumed, or
interrupted.
https://docs.python.org/2/library/threading.html#threading.ThreadError
This sample creates a thread that will run for 10 seconds. The parent then waits a second, then is "done", and waits (ie: join()s) the outstanding threads before exiting cleanly.
import sys, threading, time
class MyThread(threading.Thread):
def run(self):
for _ in range(10):
print 'ding'
time.sleep(1)
MyThread().start()
time.sleep(2)
print 'joining threads'
for thread in threading.enumerate():
if thread is not threading.current_thread():
thread.join()
print 'done'

Fabric get() progressbar

I am currently generating a python-script with the fabric framwork that is supposed to collect a backup from a remote server and store it locally on the client running fabric.
Now, since the backup file is >400MB, it takes quite some time to transfer it. And here is where my question bumps in:
Is there any kind of progressbars for the fabric get()-function? Or rather, is it possible to add a progressbar somehow?
Here's a piece of my code:
def collect_backup():
env.warn_only=True
run('uptime')
print "Copying scrips to be run..."
filename, remotepath = _getlatest()
print "Copy complete."
print "Collecting backup..."
localpath = _collect(filename, remotepath)
def _collect(filename, remotepath):
a=remotepath + filename
localpath="/home/bcns/backups/"
####Here's the get() I was talking about
get(a, localpath)
return(localpath)
The "filename" and "remotepath" variables are set in another function.
There is a lot of great info at the following site:
http://thelivingpearl.com/2012/12/31/creating-progress-bars-with-python/
Here is their solution for a console prog bar with threading:
import sys
import time
import threading
class progress_bar_loading(threading.Thread):
def run(self):
global stop
global kill
print 'Loading.... ',
sys.stdout.flush()
i = 0
while stop != True:
if (i%4) == 0:
sys.stdout.write('\b/')
elif (i%4) == 1:
sys.stdout.write('\b-')
elif (i%4) == 2:
sys.stdout.write('\b\\')
elif (i%4) == 3:
sys.stdout.write('\b|')
sys.stdout.flush()
time.sleep(0.2)
i+=1
if kill == True:
print '\b\b\b\b ABORT!',
else:
print '\b\b done!',
kill = False
stop = False
p = progress_bar_loading()
p.start()
try:
#anything you want to run.
time.sleep(1)
stop = True
except KeyboardInterrupt or EOFError:
kill = True
stop = True
Hope that helps or at least gets you started.

Categories

Resources