I have the following code which acts pretty strange.
class A:
def __init__(self):
self.lock = Lock()
self.process_list = []
self.event_list = []
def run(self):
self.process_list = []
counter = 0
n = 0
while (n<1000):
n += 1
print("in while again")
self.lock.acquire()
print('after acquired lock')
self.lock.release()
self.event_list.append(Event())
print('add event')
p = Process(target=workerEmulator().run,
args=(self.lock, self.event_list[counter]))
print('create process')
self.process_list.append(p)
print('add process')
self.event_list[counter].clear()
counter += 1
print("about to start process")
print("n="+str(n))
p.start()
print("new process started")
print(": main process, active_children: " + str(multiprocessing.active_children()))
del_list = [] # the list for storing index of the process/event to delete
for i in range(len(self.event_list)):
if (self.event_list[i].is_set()):
self.process_list[i].join()
print("one process finished, its exit code: " + str(self.process_list[i].exitcode))
print("this process is alived or not? " + str(self.process_list[i].is_alive()))
del_list.append(i)
del_list.sort(reverse=True)
for i in del_list:
del self.event_list[i]
del self.process_list[i]
counter -= 1
time.sleep(0.1)
for p in self.process_list:
p.join()
print("one process finished, its exit code: " + str(p.exitcode))
print("this process is alived or not? " + str(p.is_alive()))
class workerEmulator:
def __init__(self):
pass
def run(self, lock, event):
print("a new process")
self.lock = lock
self.event = event
time.sleep(20)
print("after sleep")
self.lock.acquire()
print("in lock")
self.lock.release()
self.event.set()
if __name__ == '__main__':
a = A()
a.run()
As I thought, every print statement should be executed 1000 times. However, it is never the case, there are always a few times missing, then if we look at n, I noticed that n will jump over some number, for example, ... n=798...n=799...n=801...n=802... (n=800 missing). I don't see why this happens, could someone help?
See Matt's comment, the problem is caused by child output intermingles with parent output.
Related
I would like to know if there is how to create two threads, one to ask some number and another to show this number typed in parallel.
from threading import Thread
global result
result = None
class OutPut(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
global result
if result is not None:
print('Number entered was: {}'.format(result))
class Write(Thread):
def __init__(self):
Thread.__init__(self);
def run(self):
global result
user_write = True
while user_write:
num = int(input('Enter a number? '))
result = num
if num == 0:
user_write = False
threadIO = Write()
threadOutPut = OutPut()
arrThread = [threadIO, threadOutPut]
for tH in arrThread:
tH.start()
for t in arrThread:
t.join()
print('===== THREADS OFF =====')
I was trying to do something with this code. The "thread" of asking until it works but showing what was typed doesn't.
I still could not pin down your exact requirements, but I think what you need is something like this...
import time
import readline
import thread
import sys
global num
num = None
def print_num():
while True:
time.sleep(5)
sys.stdout.write('\r'+' '*(len(readline.get_line_buffer())+2)+'\r')
global num
if num:
print("Writing ", num)
sys.stdout.write('Enter number > ' + readline.get_line_buffer())
sys.stdout.flush()
thread.Thread(target=print_num).start()
while True:
num = input('Enter number > ')
Here are some changes to your OutPut thread to print each result one time and also exit when 0 is input. The important part is that the OutPut thread must keep looping to check result, then reset result after printing it.
In your original code, you might consider putting a print at the end of OutPut's run function to see why the code doesn't work as you expected.
from threading import Thread
global result
result = None
class OutPut(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
global result
while True: # Loop to check the result
if result is not None:
print("Number entered was: {}".format(result))
if result == 0:
break # if result is 0, break the loop
result = None # reset the result to None, so we don't print the same result again
print("Thread finished")
class Write(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
global result
user_write = True
while user_write:
num = int(input("Enter a number? "))
result = num
if num == 0:
user_write = False
threadIO = Write()
threadOutPut = OutPut()
arrThread = [threadIO, threadOutPut]
for tH in arrThread:
tH.start()
for t in arrThread:
t.join()
print("===== THREADS OFF =====")
I have a program that is supposed to send a few data points over a serial connection to an arduino which will control some motors to move. I can send the control signals individually as well as by txt file which will run repeatedly until the file is complete. While running a txt file, I want to be able to exit the loop like a pause or stop button. I think the best way to do that is via a thread that I can close. I have never done any threading before and my rudimentary attempts have not worked. Here is the function that sends the file data.
def send_file():
# Global vars
global moto1pos
global motor2pos
# Set Ready value
global isready
# Get File location
program_file_name = file_list.get('active')
file_path = "/home/evan/Documents/bar_text_files/"
program_file = Path(file_path + program_file_name)
file = open(program_file)
pos1 = []
pos2 = []
speed1 = []
speed2 = []
accel1 = []
accel2 = []
for each in file:
vals = each.split()
pos1.append(int(vals[0]))
pos2.append(int(vals[1]))
speed1.append(int(vals[2]))
speed2.append(int(vals[3]))
accel1.append(int(vals[4]))
accel2.append(int(vals[5]))
# Send file values
try:
while isready == 1:
for i in range(len(pos1)):
print("Step: " + str(i+1))
data = struct.pack("!llhhhh", pos1[i], pos2[i], speed1[i], speed2[i], accel1[i], accel2[i])
ser.write(data)
try:
pos1time = abs(pos1[i]/speed1[i])
except:
pos1time = 0
try:
pos2time = abs(pos2[i]/speed2[i])
except:
pos2time = 0
time_array = (pos1time, pos2time)
time.sleep(max(time_array))
motor1pos = ser.readline()
motor2pos = ser.readline()
if i < (len(pos1)-1):
isready = ord(ser.read(1))
else:
isready = 0
except:
print("Error: data not sent. Check serial port is open")
Here is the threading command which I want the sendfile command to work from.
def thread():
try:
global isready
isready = 1
t = threading.Thread(name='sending_data', target=command)
t.start()
except:
print("Threading Error: you don't know what you are doing")
And here is the stop function I want the thread to be killed by:
def stop():
try:
global isready
isready = 0
t.kill()
except:
print("Error: thread wasn't killed")
I know you aren't supposed to kill a thread but the data isn't very important. Whats more important is to stop the motors before something breaks.
The button in tkinter is:
run_file_butt = tk.Button(master = file_frame, text = "Run File", command = thread)
When I click the button, the program runs but the stop function does nothing to stop the motion.
Question: run and kill a thread on a button press
There is no such a thing called .kill(....
Start making your def send_file(... a Thread object which is waiting your commands.
Note: As it stands, your inner while isready == 1: will not stop by using m.set_state('stop').
It's mandatory to start the Thread object inside:
if __name__ == '__main__':
m = MotorControl()
import threading, time
class MotorControl(threading.Thread):
def __init__(self):
super().__init__()
self.state = {'is_alive'}
self.start()
def set_state(self, state):
if state == 'stop':
state = 'idle'
self.state.add(state)
def terminate(self):
self.state = {}
# main function in a Thread object
def run(self):
# Here goes your initalisation
# ...
while 'is_alive' in self.state:
if 'start' in self.state:
isready = 1
while isready == 1:
# Here goes your activity
# Simulate activity
print('running')
time.sleep(2)
isready = 0
self.state = self.state - {'start'}
self.state.add('idle')
elif 'idle' in self.state:
print('idle')
time.sleep(1)
if __name__ == '__main__':
m = MotorControl()
time.sleep(2)
m.set_state('start')
time.sleep(3)
m.set_state('stop')
time.sleep(3)
m.set_state('start')
time.sleep(4)
m.terminate()
print('EXIT __main__')
Your tk.Button should look like:
tk.Button(text = "Run File", command = lambda:m.set_state('start'))
tk.Button(text = "Stop File", command = lambda:m.set_state('stop'))
tk.Button(text = "Terminate", command = m.terminate)
The answer I have gone with is simple due to my simple understanding of threading and unique circumstances with which I am using the threading. Instead of terminating the thread in a way I was hoping, I added another conditional statement to the sending line of the send_file function.
while isready == 1:
for i in range(len(pos1)):
if motorstop == False:
print("Step: " + str(i+1))
#data = struct.pack('!llllhhhhhhhh', pos1[i], pos2[i], pos3[i], pos4[i], speed1[i], speed2[i], speed3[i], speed[4], accel1[i], accel2[i], accel3[i], accel4[i])
data = struct.pack("!llhhhh", pos1[i], pos2[i], speed1[i], speed2[i], accel1[i], accel2[i])
ser.write(data)
else:
isready = 0
break
and I have updated my stop() func to the following:
def stop():
try:
global motorstop
global t
motorstop = True
t.join()
except:
print("Error: thread wasn't killed")
I'm not exactly sure how it works but it is much simpler than what was mentioned by #stovefl.
With this code, since the function is mostly just sleeping, it can run but it won't send any new information and then will .join() after the next iteration.
I am developing a program to produce an event whenever a speed is reached on a gps. The code I am currently trying to modify is below:
from gps import *
import time
import threading
import math
class GpsController(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.running = False
def run(self):
self.running = True
while self.running:
# grab EACH set of gpsd info to clear the buffer
self.gpsd.next()
def stopController(self):
self.running = False
#property
def fix(self):
return self.gpsd.fix
#property
def utc(self):
return self.gpsd.utc
#property
def satellites(self):
return self.gpsd.satellites
if __name__ == '__main__':
# create the controller
gpsc = GpsController()
try:
# start controller
gpsc.start()
while True:
#print "latitude ", gpsc.fix.laif
#print "longitude ", gpsc.fix.longitude
#print "time utc ", gpsc.utc, " + ", gpsc.fix.time
#print "altitude (m)", gpsc.fix.altitude
#print "eps ", gpsc.fix.eps
#print "epx ", gpsc.fix.epx
#print "epv ", gpsc.fix.epv
#print "ept ", gpsc.gpsd.fix.ept
print "speed (m/s) ", gpsc.fix.speed
#print "climb ", gpsc.fix.climb
#print "track ", gpsc.fix.track
#print "mode ", gpsc.fix.mode
#print "sats ", gpsc.satellites
time.sleep(1)
#Error
#except:
# print "Unexpected error:", sys.exc_info()[0]
# raise
#Ctrl C
except KeyboardInterrupt:
print "User cancelled"
finally:
print "Stopping gps controller"
gpsc.stopController()
#wait for the thread to finish
gpsc.join()
print "Done"
I am wanting to add an "if" statement to the program to first look at the speed being transmitted and printing or enabling an event whenever the speed reaches a certain number.
I am not sure where and when to add the "if" code.
In the while loop would make the most sense. There was no specification as to whether the event should happen once or multiple times when hitting the 'certain amount'.
from gps import *
import time
import threading
import math
class GpsController(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.gpsd = gps(mode=WATCH_ENABLE) #starting the stream of info
self.running = False
def run(self):
self.running = True
while self.running:
# grab EACH set of gpsd info to clear the buffer
self.gpsd.next()
def stopController(self):
self.running = False
#property
def fix(self):
return self.gpsd.fix
#property
def utc(self):
return self.gpsd.utc
#property
def satellites(self):
return self.gpsd.satellites
if __name__ == '__main__':
# create the controller
gpsc = GpsController()
try:
# start controller
gpsc.start()
while True:
if gspc.fix.speed > event_trigger_amt:
print "speed (m/s) ", gpsc.fix.speed
doEvent()
time.sleep(1)
#Ctrl C
except KeyboardInterrupt:
print "User cancelled"
finally:
print "Stopping gps controller"
gpsc.stopController()
#wait for the thread to finish
gpsc.join()
I've made a python script that factorizes a number into its prime factors. However when dealing with big numbers i may like to have an idea to the progress of the computation. (I simplified the script)
import time, sys, threading
num = int(input("Input the number to factor: "))
factors = []
def check_progress():
but = input("Press p: ")
if but == "p":
tot = int(num**(1/2))
print("Step ", k, " of ", tot, " -- ", round(k*100/tot,5), "%", end="\r", sep="")
t = threading.Thread(target=check_progress) ?
t.daemon = True ?
t.start() ?
k = 1
while(k != int(num**(1/2))):
k = (k+1)
if num%k == 0:
factors.append(int(k))
num = num//k
k = 1
print(factors)
I'm wondering if there is a way to show the progress on demand, for example, during the loop, i press a key and it prints the progress?
How can i implement a thread of something like that in my script?
Thanks and sorry for my english
Edit:
def check_progress():
while True:
but = input("## Press return to show progress ##")
tot = int(num**(1/2))
print("Step ", k, " of ", tot, " -- ", round(k*100/tot,5), "%", sep="")
Here is one possible design:
Main thread:
create queue and thread
start the progress thread
wait user input
on input:
pop result from queue (may be None)
display it
loop
Progress thread:
do the work an put status in queue
I can provide example, but I feel you are willing to learn. Feel free to comment for help.
Edit: Full example with queue.
from time import sleep
from Queue import Queue
from threading import Thread
# Main thread:
def main():
# create queue and thread
queue = Queue()
thread = Thread(target=worker, args=(queue,))
# start the progress thread
thread.start()
# wait user input
while thread.isAlive():
raw_input('--- Press any key to show status ---')
# pop result from queue (may be None)
status = queue.get_nowait()
queue.task_done()
# display it
if status:
print 'Progress: %s%%' % status
else:
print 'No status available'
# Progress thread:
def worker(queue):
# do the work an put status in queue
# Simulate long work ...
for x in xrange(100):
# put status in queue
queue.put_nowait(x)
sleep(.5)
if __name__ == '__main__':
main()
from __future__ import print_function
from threading import Semaphore, Lock, Thread
from time import sleep
from random import random
import argparse
from timeit import Timer
(THINKING, EATING) = (0, 1) #philosopher states
def left_fork(id):
return id
def right_fork(id):
return (id+1) % NUM_PHILOSOPHER
def right(id):
return (id+1) % NUM_PHILOSOPHER
def left(id):
return (id+NUM_PHILOSOPHER-1) % NUM_PHILOSOPHER
def get_fork(id):
global mutex
global tstate
global sem
mutex.acquire()
tstate[id] = 'hungry'
test(id)
mutex.release()
sem[id].acquire()
def put_fork(id):
global mutex
global tstate
global sem
mutex.acquire()
tstate[id] = 'thinking'
test(right(id))
test(left(id))
mutex.release()
def test(id):
global tstate
if tstate[id] == 'hungry' and tstate[left(id)] != 'eating' and tstate[right(id)] != 'eating':
tstate[id] = 'eating'
sem[id].release()
def philosophize_footman(id,meal):
global forks
global footman
state = THINKING
for i in range(meal):
sleep(random())
if(state == THINKING):
msg = "Philosopher " + str(id) + " is thinking."
#print(msg)
footman.acquire()
forks[right_fork(id)].acquire()
forks[left_fork(id)].acquire()
state = EATING
else:
msg = "Philosopher " + str(id) + " is eating."
#print(msg)
forks[right_fork(id)].release()
forks[left_fork(id)].release()
state = THINKING
footman.release()
print("Finish philosophize_footman")
def philosophize_lefthand(id,meal):
global forks
state = THINKING
for i in range(meal):
sleep(random())
if(state == THINKING):
#define the left hand user.
if(id == 3):
forks[left_fork(id)].acquire()
forks[right_fork(id)].acquire()
state = EATING
else:
forks[right_fork(id)].acquire()
forks[left_fork(id)].acquire()
state = EATING
else:
if(id == 3):
forks[left_fork(id)].release()
forks[right_fork(id)].release()
state == THINKING
else:
forks[right_fork(id)].release()
forks[left_fork(id)].release()
state == THINKING
print("Finish philosophize_lefthand")
def philosophize_Tanenbaum(id,meal):
for i in range(meal):
get_fork(id)
sleep(random())
put_fork(id)
print("Finish philosophize_Tanenbaum")
def run_c(numP,numM):
for m in range(numP):
phil1 = Thread(target = philosophize_Tanenbaum,args = (m,numM))
phil1.start()
def run_a():
global NUM_PHILOSOPHER
global MEAL
for i in range(NUM_PHILOSOPHER):
phil = Thread(target = philosophize_footman, args = (i,MEAL))
phil.start()
def run_b(numP,numM):
for n in range(numP):
phil2 = Thread(target = philosophize_lefthand, args = (n,numM))
phil2.start()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description = 'Philosopher dining')
parser.add_argument('--nphi','-n',
type = int,
default = 5,
help = 'add num_phi',
metavar = 'number of philosophers')
parser.add_argument('--meal','-m',
type = int,
default = 100,
help = 'number of meals',
metavar = 'meal')
args = parser.parse_args()
NUM_PHILOSOPHER = args.nphi #define number fo philosophers
MEAL = args.meal #define number of meals
forks = [Semaphore(1) for i in range(NUM_PHILOSOPHER)] #defines forks
sem = [Semaphore(0) for i in range(NUM_PHILOSOPHER)] #semaphores
footman = Semaphore(4) #limit the number of philosophers
mutex = Semaphore(1) #mutex
tstate = ['thinking'] * NUM_PHILOSOPHER #T-states
run_a()
# run_b(args.nphi,args.meal)
# run_c(args.nphi,args.meal)
timer = Timer(run_a)
print("Time:{:0.3f}s".format(timer. timeit(100)/100))
It is dinning philosopher problem solution by python. The code is listed above. I want to measure the running time of function run_a(). But when using timer, I found it doesn't work well. It prints the time result immediately(e.g 0.001s, but the code is still running.) So please help me with it! Thank you very much.
You need to wait for the threads to finish; call Thread.join() on each thread:
def run_a():
global NUM_PHILOSOPHER
global MEAL
threads = []
for i in range(NUM_PHILOSOPHER):
phil = Thread(target = philosophize_footman, args = (i,MEAL))
phil.start()
threads.append(phil)
for t in threads:
t.join()
The Thread.join() method blocks until the thread has completed, or you can specify a timeout.