Send file pointer to python thread and update file pointer - python

I have a python program with a thread and the thread should write into a file. I will spawn a thread from the main program. Now on new day trigger I will change the file pointer in the main program and I want the thread also to take the new file to write the data to the file.
I have a code which will take global variable and do this task. But is there any other better way of doing this?
#!/usr/bin/env python
import sys
import threading
import time
filePtr = None
import time
def fileWriteTh():
global filePtr
time.sleep(2)
filePtr.write("from the thrread this should in file 2")
def main():
global filePtr
filePtr = open("test1.txt","ab")
fileThread = threading.Thread(target=fileWriteTh)
fileThread.start()
if new_day_trigger:
filePtr.close()
filePtr = open("test2.txt","ab")
fileThread.join()
if __name__ == "__main__":
main()
This is the new code that is written:
#!/usr/bin/env python
import sys
import threading
import time
class SendPacket(object):
fileDesc = None
def __init__(self, fd):
super(SendPacket, self).__init__()
SendPacket.fileDesc = fd
def printFromInstance(self,var):
print var
SendPacket.fileDesc.write(var)
time.sleep(3)
print var
SendPacket.fileDesc.write(var)
def startabc(self, someVar):
self.printFromInstance(someVar)
#classmethod
def printVar(cls, printStr):
print printStr
cls.fileDesc.write(printStr)
#classmethod
def changeClsFile(cls, newFd):
cls.fileDesc = newFd
def main():
filePtr = open("test1.txt","ab")
sendPack_inst = SendPacket(filePtr)
fileThread = threading.Thread(target=sendPack_inst.startabc, args=("test1",))
fileThread.start()
time.sleep(2)
filePtr.close()
filePtr = open("test2.txt","ab")
SendPacket.changeClsFile(filePtr)
fileThread.join()
filePtr.close()
if __name__ == "__main__":
main()

Like this:
#!/usr/bin/env python
import sys
import thread
import time
class _fileACT :
def __init__(self):
self.trigger = 0
self.flag = True
self.msg = ""
self.files = (open("test1.txt","ab"),open("test2.txt","ab"))
def run(self,pssrg):
while self.flag :
if self.msg != "" :
self.files[self.trigger].write(self.msg)
self.msg = ""
def test(self,pssrg):
for i in range(20):
time.sleep(1)
if i %2 != 0 :
self.trigger = 0
elif i %2 != 1:
self.trigger = 1
self.msg = "%0.3d test-1,asdasdasd\n"%i
time.sleep(0.5)
print "wait..."
self.flag = False
for e in self.files : e.close()
print "can exit !"
if __name__ == "__main__":
fileACT = _fileACT()
thread.start_new_thread(fileACT.run,(None,))
thread.start_new_thread(fileACT.test,(None,))
We have three variables, filename, last opened file name and message. Two files, only False and True will be sufficient (of course you can use index for multiple files). We've written a test function into the class because we don't want our main cycle to freeze. The file selection is done with ' trigger ', but the previous and next file name is not the same, the previous closes.
The important point in the thread is that the time delay is strictly unavailable! The time delay is always applied to the trigger. The time delay cannot be placed in the main loop. An instance of access from outside the class is also attached. I hope it helps.

Related

Wait for class variable change with threading

I have tried the following code snippets. It exists in two separate .py files ChrMain.py and xlWingsTest.py
The meaning is to wait in the main code until excel trigger the class value to True. The code gives no errors but it doesn't trigger the main code. I don't like to use sleep in the code. The main code is already running when excel and xlWings execute the trigger.
Main Code
from waiting import wait as Wait
import time
import threading
class RunSub:
RunNu = False
class RunMain:
isRun = True
def ChrMain():
while RunMain.isRun:
try:
print('Sub is waiting')
Wait(lambda : RunSub.RunNu, timeout_seconds = 40)
print('Sub is continueing ...')
# Do other Stuff
time.sleep(5) # This line is only for testing
RunMain.isRun = False
except:
pass
m = threading.Thread(name = 'Main', target = ChrMain())
m.start()
print('Program End')
exit()
***Trigger Code***
import xlwings as xw
def SetRunNow(myBool):
if myBool:
RunSub.RunNu = True
else:
RunSub.RunNu = False
def StopProg(myBool):
if myBool:
RunMain.isRun = True
else:
RunMain.isRun = False
#xw.func
def Injector(myBool, strfunctie):
import threading
if strfunctie == 'SetRunNow':
from ChrMain import RunSub
i = threading.Thread(name = 'RunNow', target = SetRunNow(myBool))
i.start()
i.join()
return RunSub.RunNu
elif strfunctie == 'StopProg':
from ChrMain import RunMain
i = threading.Thread(name = 'StopProg', target = StopProg(myBool))
i.start()
i.join()
return RunMain.isRun
#exit()
This line might have a bug: i = threading.Thread(name = 'RunNow', target = SetRunNow(myBool))
target must be a function, but SetRunNow(myBool) is a boolean.
a way to fix this would be:
i = threading.Thread(name = 'RunNow', target = lambda: SetRunNow(myBool))

Why can't I start two threads inside constructor __init__() of a python class?

I'm simply trying to run two different daemon threads and print a line from each for testing. While this code works :
import time
import threading
from threading import Thread
from myFunctions import *
class Monitoring:
def alarms(self):
return alarms.run()
def generator(self):
return generator.run()
def run(self):
generator = threading.Thread(target=self.alarms)
generator.daemon = True
generator.start()
alarm = threading.Thread(target=self.generator)
alarm.daemon = True
alarm.start()
print("started thread")
if __name__ == '__main__':
try:
d = Monitoring()
d.daemon = True
d.run()
print("started the thread")
while 1:
time.sleep(1)
except KeyboardInterrupt:
alarms.close()
generator.close()
print("Main - Keyboard interrupt in __main__")
Something like this doesn't seem to work and only the first thread "alarms" start. Why is that?
class Monitoring:
def __init__(self,a,g):
self.a = a
self.g = g
def run(self):
generator = threading.Thread(target=self.a)
generator.daemon = True
generator.start()
alarm = threading.Thread(target=self.g)
alarm.daemon = True
alarm.start()
print("#class run() ")
if __name__ == '__main__':
try:
d = Monitoring(alarms.run(), generator.run())
d.daemon = True
d.run()
print("#__main__")
while 1:
time.sleep(1)
except KeyboardInterrupt:
alarms.close()
generator.close()
print("Main - Keyboard interrupt in __main__")
In the line
d = Monitoring(alarms.run(), generator.run())
the functions alarms.run and generator.run are called instantly and the return values (probably None) are given as arguments to the Monitoring constructor.
To use the function objects as arguments (which are then called in a new thread), use
d = Monitoring(alarms.run, generator.run)
instead.

Python threaded class calls another threaded class (queue help)

I am trying to control a 3-axis printer using an x-box controller. To get inputs from the x-box I have borrowed code from martinohanlon https://github.com/martinohanlon/XboxController/blob/master/XboxController.py
I have also created code that reads a text file line by line (G-code) to move the printer.
I would like to be able to use the X-Box controller to select a G-code file and run it, then as the printer is running continue to listen for a cancel button just in case the print goes wrong. The controller is a threaded class, and my readGcode is a threaded class.
The problem I'm having is that when I use the controller to start the readGcode class I cant communicate with the controller until that thread finished.
My temporary solution is to use the controller to select a file then pass that files path to the readGcode class. In the readGcode class it keeps trying to open a file using a try block and fails until the filepath is acceptable. Then it changes a bool which makes it skip further reading until its done.
Code:
import V2_Controller as Controller
import V2_ReadFile as Read
import time
import sys
# file daialogue
import tkinter as tk
from tkinter import filedialog
# when X is selected on the x-box controller
def X(xValue):
if not bool(xValue):
try:
f=selectfile()
rf.setfilename(f)
except:
print("failed to select file")
def selectfile():
try:
root = tk.Tk() # opens tkinter
root.withdraw() # closes the tkinter window
return filedialog.askopenfilename()
except Exception:
print("no file")
# setup xbox controller
xboxCont = Controller.XboxController(controlCallBack, deadzone=30,
scale=100, invertYAxis=True)
# init the readfile class
rf = Read.Readfile()
# set the custom function for pressing X
xboxCont.setupControlCallback(xboxCont.XboxControls.X, X)
try:
# start the controller and readfile threads
xboxCont.start()
rf.start()
xboxCont.join()
rf.join()
while True:
time.sleep(1)
# Ctrl C
except KeyboardInterrupt:
print("User cancelled")
# error
except:
print("Unexpected error:", sys.exc_info()[0])
raise
finally:
# stop the controller
xboxCont.stop()
rf.stop()
V2_Readfile
# Main class for reading the script
class Readfile(threading.Thread):
# supports all variables needed to read a script
class readfile:
fileselect = True
linecount = 0
currentline = 0
commands = []
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
def setfilename(self,filename):
self.filename = filename
# called by the thread
def run(self):
self._start()
# start reading
def _start(self):
self.running = True
while self.running:
time.sleep(1)
if not self.reading:
try:
self.startread()
except:
pass
def startread(self):
try:
with open(self.filename, "r") as f: # read a local file
f1 = f.readlines()
# run through each line and extract the command from each line
linecount = 0
line = []
for x in f1:
# read each line into an array
line.append(x.split(";")[0])
linecount += 1
# Store the variables for later use
self.readfile.linecount = linecount
self.readfile.commands = line
self.reading = True
except Exception:
pass
i = 0
while i < self.readfile.linecount and self.reading:
self.readfile.currentline = i + 1
self.readline(i)
i += 1
# the following stops the code from reading again
self.reading = False
self.filename = ""
def readline(self,line):
Sort.sortline(self.readfile.commands[line])
# stops the controller
def stop(self):
self.running = False
You could use a syncronization primitive like threading.Event.
To do so, you need to modify your Readfile class like this:
from threading import Event
class Readfile(threading.Thread):
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
self.reading_file = Event() # Initialize your event here it here
def setfilename(self,filename):
self.filename = filename
self.reading_file.set() # This awakens the reader
def _start(self):
self.running = True
self.reading_file.wait() # Thread will be stopped until readfilename is called
self.startread()
Another syncronization primitive worth exploring is queue.Queue. It could be useful if you want to process more than one filename.
The pattern you describe in your question is called Busy Waiting, and should be avoided when possible.

Multiple inheritance of class and threading in Python

I have an annoying problem in Python concerning the heritage of class.
The code is the following:
import time
from threading import Thread
class Main:
def __init__(self):
self.var = 0
self.fils_on()
def fils_on(self):
self.temp = Fils()
self.temp.start()
def fils_off(self):
self.temp.stop()
del self.temp
class Fils(Thread, Main):
def __init__(self):
Main.__init__(self)
Thread.__init__(self)
self.encore = True
def run(self):
i = 0
while self.encore:
chaine = str(i)
print chaine
print "var: ", self.var
i += 1
time.sleep(1)
def stop(self):
self.encore = False
if __name__ == "__main__":
main = Main()
My problem is when I call "Main", I don't manage to print the self.var variable from Fils class.
Someone know why?
And how can I fix it?
I don't understand what you are trying to achieve but it seems you are trying to experiment with threads, The above implementation exceeds recursion depth because you have a cyclic dependency, __init__ from Main class depends on self.fils_on() and it construct Fils() which trigger Fils.__init__() which in turn calls Main.__init__(self) and again the whole process continues.
Here I tried to modify your code, in which I removed the inheritance between Fils and Mains and moved var inside Fils.
import time
from threading import Thread
class Main:
def __init__(self):
self.fils_on()
def fils_on(self):
self.temp = Fils()
self.temp.start()
def fils_off(self):
self.temp.stop()
del self.temp
class Fils(Thread):
def __init__(self):
Thread.__init__(self)
self.encore = True
self.var = 0
def run(self):
i = 0
while self.encore:
chaine = str(i)
print chaine
print "var: ", self.var
i += 1
time.sleep(1)
def stop(self):
self.encore = False
if __name__ == "__main__":
main = Main()

Cancellable threading.Timer in Python

I am trying to write a method that counts down to a given time and unless a restart command is given, it will execute the task. But I don't think Python threading.Timer class allows for timer to be cancelable.
import threading
def countdown(action):
def printText():
print 'hello!'
t = threading.Timer(5.0, printText)
if (action == 'reset'):
t.cancel()
t.start()
I know the above code is wrong somehow. Would appreciate some kind guidance over here.
You would call the cancel method after you start the timer:
import time
import threading
def hello():
print "hello, world"
time.sleep(2)
t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
t.cancel()
You might consider using a while-loop on a Thread, instead of using a Timer.
Here is an example appropriated from Nikolaus Gradwohl's answer to another question:
import threading
import time
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.count = 10
def run(self):
while self.count > 0 and not self.event.is_set():
print self.count
self.count -= 1
self.event.wait(1)
def stop(self):
self.event.set()
tmr = TimerClass()
tmr.start()
time.sleep(3)
tmr.stop()
I'm not sure if I understand correctly. Do you want to write something like in this example?
>>> import threading
>>> t = None
>>>
>>> def sayHello():
... global t
... print "Hello!"
... t = threading.Timer(0.5, sayHello)
... t.start()
...
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>
The threading.Timer class does have a cancel method, and although it won't cancel the thread, it will stop the timer from actually firing. What actually happens is that the cancel method sets a threading.Event, and the thread actually executing the threading.Timer will check that event after it's done waiting and before it actually executes the callback.
That said, timers are usually implemented without using a separate thread for each one. The best way to do it depends on what your program is actually doing (while waiting for this timer), but anything with an event loop, like GUI and network frameworks, all have ways to request a timer that is hooked into the eventloop.
Im not sure if best option but for me is woking like this:
t = timer_mgr(.....) append to list "timers.append(t)" and then after all created you can call:
for tm in timers:#threading.enumerate():
print "********", tm.cancel()
my timer_mgr() class is this:
class timer_mgr():
def __init__(self, st, t, hFunction, id, name):
self.is_list = (type(st) is list)
self.st = st
self.t = t
self.id = id
self.hFunction = hFunction
self.thread = threading.Timer(t, self.handle_function, [id])
self.thread.name = name
def handle_function(self, id):
if self.is_list:
print "run_at_time:", datetime.now()
self.hFunction(id)
dt = schedule_fixed_times(datetime.now(), self.st)
print "next:", dt
self.t = (dt-datetime.now()).total_seconds()
else:
self.t = self.st
print "run_every", self.t, datetime.now()
self.hFunction(id)
self.thread = threading.Timer(self.t, self.handle_function, [id])
self.thread.start()
def start(self):
self.thread.start()
def cancel(self):
self.thread.cancel()
Inspired by above post.
Cancelable and Resetting Timer in Python. It uses thread.
Features: Start, Stop, Restart, callback function.
Input: Timeout, sleep_chunk values, and callback_function.
Can use or inherit this class in any other program. Can also pass arguments to the callback function.
Timer should respond in middle also. Not just after completion of full sleep time. So instead of using one full sleep, using small chunks of sleep and kept checking event object in loop.
import threading
import time
class TimerThread(threading.Thread):
def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
threading.Thread.__init__(self)
self.timeout = timeout
self.sleep_chunk = sleep_chunk
if callback == None:
self.callback = None
else:
self.callback = callback
self.callback_args = args
self.terminate_event = threading.Event()
self.start_event = threading.Event()
self.reset_event = threading.Event()
self.count = self.timeout/self.sleep_chunk
def run(self):
while not self.terminate_event.is_set():
while self.count > 0 and self.start_event.is_set():
# print self.count
# time.sleep(self.sleep_chunk)
# if self.reset_event.is_set():
if self.reset_event.wait(self.sleep_chunk): # wait for a small chunk of timeout
self.reset_event.clear()
self.count = self.timeout/self.sleep_chunk # reset
self.count -= 1
if self.count <= 0:
self.start_event.clear()
#print 'timeout. calling function...'
self.callback(*self.callback_args)
self.count = self.timeout/self.sleep_chunk #reset
def start_timer(self):
self.start_event.set()
def stop_timer(self):
self.start_event.clear()
self.count = self.timeout / self.sleep_chunk # reset
def restart_timer(self):
# reset only if timer is running. otherwise start timer afresh
if self.start_event.is_set():
self.reset_event.set()
else:
self.start_event.set()
def terminate(self):
self.terminate_event.set()
#=================================================================
def my_callback_function():
print 'timeout, do this...'
timeout = 6 # sec
sleep_chunk = .25 # sec
tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
tmr.start()
quit = '0'
while True:
quit = raw_input("Proceed or quit: ")
if quit == 'q':
tmr.terminate()
tmr.join()
break
tmr.start_timer()
if raw_input("Stop ? : ") == 's':
tmr.stop_timer()
if raw_input("Restart ? : ") == 'r':
tmr.restart_timer()

Categories