Suspected thread issue with pyinotify - python

I have been working with pyinotify and I am having issues with it where after multiple changes to a folder it simply stops receiving notifications. I have a feeling it is something to do with the the fact that two threads are running; namely the notifier thread and the wxpython thread.
The purpose of the app is to essentially load a picture to the screen when it detects an ip connection, monitor a folder for the file 'Checklist' and based on that file do some processing i.e move files around.
It works intermittently but being a python newbie Im not exactly sure what the issue might be as I have basically taken the threaded example and worked around it. Sometimes, it only gets one notification and stops receiving file change notifications.
Additionally, if I restart the linux box and try again, it works for a good number of file changes and then stops receiving notifications again which makes me think that perhaps its not releasing the watches properly?
Any help would be greatly appreciated as well as optimizations and improvements are very welcome. I'm sure I could learn a lot from the feedback. The code is below
import pyinotify
import os.path
import shutil
import errno
import subprocess
import logging
import wx
import time
import signal
import sys
#update CHECKLIST name
CHECKLIST = 'Checklist' #this must exist in the update archive
#static values
DIR_UPDATE = 'd'
FILE_UPDATE = 'f'
PING_IP = ' localhost' # change in production
#paths
WATCH_PATH = '/home/test'
LOG_PATH = '/home/test/update.log'
CONNECTED_IMG = 'update.jpg'
UPDATING_IMG = 'updating.png'
#msgs
UPDATEFOUND_MSG = ' Update Found '
UPDATEUNZIPPEDSTART_MSG = ' Update unzipping '
UPDATEUNZIPPED_MSG = ' Update unzipped '
UPDATEFILE_MSG = ' Update file '
UPDATEFILEMSG_CONT = ' moved into path '
REMOVEFILEMSG_CONT = ' removed from update folder '
UPDATECOMPLETE_CONT = ' Update complete'
ROADANGELRESTART_MSG = ' Update restarting app '
DIRCREATED_MSG = ' Directory created at path '
#errors
UPDATEFAILED_MSG = ' Update process failed on '
BADLYFORMED_MSG = ' Badly formed src/dest combination '
UPDATESRCUNAVAILABLE = ' Invalid update file specified '
UPDATEDESTUNAVAILABLE = ' Invalid update destination specified '
INVALIDUPDATEFORMAT = ' Invalid format string '
#on startup create the watchfolder if it doesnt exist
WM = pyinotify.WatchManager() # Watch Manager
WM_MASK = pyinotify.IN_CLOSE_WRITE # watched events
#setup logger
LOGGER = logging.getLogger('Updater')
LOG_HANDLE = logging.FileHandler(LOG_PATH)
FORMATTER = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
LOG_HANDLE.setFormatter(FORMATTER)
LOGGER.addHandler(LOG_HANDLE)
LOGGER.setLevel(logging.INFO)
#Global values used primarily in the main function loop
HANDLER = None
NOTIFIER = None
WDD = None
UPDATE_UI = None
WINDOW = None
CURR_IMG = None
LAST_CURRIMG = None
class EventHandler(pyinotify.ProcessEvent):
VERBOSE = False
""" Main class to monitor file events and process accordingly"""
def process_IN_CLOSE_WRITE(self, event):
""" Only executes when a Checklist has finished being written to"""
path = event.pathname
print 'evt'
#look for the update_ready file before processing
if (os.path.basename(path) == 'Checklist'):
EventHandler.parse_updates(WATCH_PATH)
global CURR_IMG
CURR_IMG = os.path.join(WATCH_PATH, UPDATING_IMG)
show_window()
print 'update completed'
time.sleep(1000)
#classmethod
def parse_updates(cls, path):
""" parses update files """
#handle errors for opening the file
file_path = os.path.join(path, CHECKLIST)
print file_path
files = open(file_path)
#handle errors for malformed tuples-done
#handle errors for unavailable files-done
#handle errors for unavailable dests-done #created automatically
#handle permission errors
for line in files:
#remove linebreaks etc and ensure its not empty
if line.strip():
array = line.split('=')
length = len(array)
if length == 3:
EventHandler.process_line(path, array)
else:
if length > 0:
EventHandler.print_bad_msg(array[0])
else:
EventHandler.print_bad_msg()
print 'removing ', file_path
os.remove(file_path) #remove the checklist file
#classmethod
def mkdir(cls, path):
""" makes a directory from a path"""
try:
os.mkdir(path)
print DIRCREATED_MSG, path
except OSError, err:
print err
if err.errno != errno.EEXIST: #thrown when the dir already exists
return False
#classmethod
def move_file(cls, src, dest):
""" moves a file from src to dest and remove after
expects that the dest already exists at this point
otherwise ignores the move"""
#print 'moving from', src, 'to ', dest
if os.path.isfile(dest):
shutil.copy2(src, dest)
else:
print UPDATEDESTUNAVAILABLE
#remove the src file when done
os.remove(src)
#classmethod
def process_line(cls, path, array):
""" process a line from the checklist"""
#remove newlines etc
update_file = array[0].strip()
update_src = os.path.join(path, update_file)
update_dest = array[1].strip()
update_type = array[2].strip()
#ensure we have valid values in all three fields
if update_file and update_dest and update_type:
#ensure the src file exists
if os.path.isfile(update_src):
#check if destination is directory and
#copy the file into the directory
if update_type == DIR_UPDATE:
EventHandler.mkdir(update_dest)
dest = os.path.join(update_dest, update_file)
EventHandler.move_file(update_src, dest)
else:
EventHandler.move_file(update_src, update_dest)
else:
print UPDATESRCUNAVAILABLE
else:
print INVALIDUPDATEFORMAT
#classmethod
def print_bad_msg(cls, msg = ''):
""" print a badly formed message with optional value"""
if msg:
print BADLYFORMED_MSG, msg
else:
print BADLYFORMED_MSG
class UpdateFrame(wx.Frame):
""" Displays update images to screen"""
def __init__(self, path):
wx.Frame.__init__(self, None, wx.ID_ANY)
image_file = path
image = wx.Bitmap(image_file)
image_size = image.GetSize()
# set the frame size to fit the screen size
self.SetClientSize(wx.DisplaySize())
# bitmap's upper left corner is in frame position (x, y)
# by default pos=(0, 0)
wx.StaticBitmap(self, wx.ID_ANY, image, size = image_size)
# the parent is the frame
self.SetTitle('Update Mode')
def ping_ip():
""" ping once to establish connection """
ret = subprocess.call("ping -c 1 %s" % PING_IP,
shell=True,
stdout=open('/dev/null', 'w'),
stderr=subprocess.STDOUT)
if ret == 0:
return True
else:
return False
def show_window():
""" update screen window when currimage changes is set """
global UPDATE_UI
global WINDOW
global CURR_IMG
global LAST_CURRIMG
if LAST_CURRIMG != CURR_IMG:
if not UPDATE_UI:
UPDATE_UI = wx.App()
if not WINDOW:
WINDOW = UpdateFrame(CURR_IMG)
UPDATE_UI.ExitMainLoop()
while(UPDATE_UI.IsMainLoopRunning()):
pass
WINDOW.Destroy()
WINDOW = UpdateFrame(CURR_IMG)
WINDOW.Show(True)
UPDATE_UI.MainLoop()
LAST_CURRIMG = CURR_IMG
print 'changed'
def in_updatemode():
return ping_ip()
while True:
try:
if not in_updatemode():
print 'waiting for connect'
time.sleep(3)
if NOTIFIER:
NOTIFIER.stop()
else:
if not HANDLER:
HANDLER = EventHandler()
if not NOTIFIER:
NOTIFIER = pyinotify.ThreadedNotifier(WM, HANDLER)
NOTIFIER.start()
if not WDD:
WDD = WM.add_watch(WATCH_PATH, WM_MASK, rec=True,quiet=False)
# ip is active so show the image and start the notifier
# state = ip active
CURR_IMG = os.path.join(WATCH_PATH, CONNECTED_IMG)
show_window()
print 'here'
except KeyboardInterrupt:
print 'out'
NOTIFIER.stop()
break

I basically found out that that the issue was indeed the fact that pyinotify's threaded notifier and wxPython's main loop dont play nice together.
The solution was to create a custom main loop (something I didn't know you could do in the first place) and place the pyinotify's threaded notifier within that loop. That way it ran as part of the wxPython main loop.
I got the idea from
http://www.java2s.com/Open-Source/Python/GUI/wxPython/wxPython-src-2.8.11.0/wxPython/samples/mainloop/mainloop.py.htm
Code below explains the concept
class CustomApp(wx.App):
def MainLoop(self):
global HANDLER
global WM
global NOTIFIER
global WDD
global UPDATE_UI
global PING_TIMER
# Create an event loop and make it active. If you are
# only going to temporarily have a nested event loop then
# you should get a reference to the old one and set it as
# the active event loop when you are done with this one...
evtloop = wx.EventLoop()
old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(evtloop)
# This outer loop determines when to exit the application,
# for this example we let the main frame reset this flag
# when it closes.
while self.keepGoing:
# At this point in the outer loop you could do
# whatever you implemented your own MainLoop for. It
# should be quick and non-blocking, otherwise your GUI
# will freeze.
# call_your_code_here()
if not HANDLER:
HANDLER = EventHandler()
if not WM:
WM = pyinotify.WatchManager() # Watch Manager
if not NOTIFIER:
NOTIFIER = pyinotify.ThreadedNotifier(WM, HANDLER)
NOTIFIER.start()
print 'notifier started'
if not WDD:
WDD = WM.add_watch(WATCH_PATH, WM_MASK, rec=True,quiet=False)
# This inner loop will process any GUI events
# until there are no more waiting.
while evtloop.Pending():
evtloop.Dispatch()
# Send idle events to idle handlers. You may want to
# throttle this back a bit somehow so there is not too
# much CPU time spent in the idle handlers. For this
# example, I'll just snooze a little...
time.sleep(0.10)
self.ProcessIdle()
wx.EventLoop.SetActive(old)
def OnInit(self):
global UPDATE_UI
if not UPDATE_UI:
UPDATE_UI = Updater()
UPDATE_UI.Show()
self.SetTopWindow(UPDATE_UI)
self.keepGoing = True
return True
"--------------------------------------------------------------------------------------"
Watcher()
app = CustomApp(False)
Additionally, I wanted to catch SIGINT in the program and I solved it using the recipe from this url
http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/
Hope this helps another python newbie or oldie :)

Related

Restart thread after exception on Python

I wrote this script in order to extract metadata from data on specific ftp then save it on specific directory and waits a random time and extract again etc...
So there is 2 points :
First : to extract from specific ftp
Second : to save it and wait a random time which depends of the ftp used.
Sometime I have timeout issue from ftp. When it occurs there is no extract, save or waiting from the thread anymore. The others thread continue to work until they meet a timeout issue too.
I tried to catch exception in order to "restart" the thread which concerns by the ftp timeout issue. But nothing changes.
Someone please can help me to find a way to "restart" the thread?
Many thank's
class ftp_id(Thread):
def __init__(self, ftpID):
Thread.__init__(self)
self.ftpID = ftpID
def run(self):
while True:
with verrou:
siteID = self.ftpID
directory = str(datetime.now())[:-16].replace('-', '')
filename = siteID + '_' + str(datetime.now())[:-7].replace(':', '').replace(' ', '_').replace('-', '') + '.txt'
dictstr = myExtract(siteID)
myWriteFile(directory, filename, dictstr)
pendingtime = myWaiting(siteID, dictstr)
time.sleep(pendingtime)
except :
self.stop = True
self.stop = False
self.start()
self.join()
thread_01 = ftp_id("ftp-01")
thread_02 = ftp_id("ftp-02")
thread_03 = ftp_id("ftp-03")
thread_04 = ftp_id("ftp-04")
thread_01.start()
thread_02.start()
thread_03.start()
thread_04.start()
thread_01.join()
thread_02.join()
thread_03.join()
thread_04.join()
Threads cannot be restarted. So you should put the exception handling inside the while-block, and never exit the loop:
def download(server):
while True:
try:
with verrou:
now = datetime.now()
directory = '{:%Y%m%d}'.format(now)
filename = '{}_{:%Y%m%d_%H%M%S}.txt'.format(server, now)
dictstr = myExtract(server)
myWriteFile(directory, filename, dictstr)
pendingtime = myWaiting(server, dictstr)
time.sleep(pendingtime)
except:
# restart
pass
threads = [
Thread(target=download, args=(server,))
for server in ["ftp-01", "ftp-02", "ftp-03", "ftp-04"
]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
threads cannot be restarted in python ... of coarse you could just implement your own "thread" class thats not really a thread
class ftp_id(object): # this is a bad name for a class please see pep8
def __init__(self, ftpID):
super(ftp_id,self)
self.ftpID = ftpID
self.thread = None
self.thread_stop = False
def __getattr__(self):
return getattr(self.thread)
def start(self):
if self.thread:
self.thread_stop = True
self.thread.terminate()
self.thread.join()
self.thread = threading.Thread(target = self.run)
self.thread.start()
def run(self):
self.thread_stop = False
while not self.thread_stop:
with verrou:
siteID = self.ftpID
directory = str(datetime.now())[:-16].replace('-', '')
filename = siteID + '_' + str(datetime.now())[:-7].replace(':', '').replace(' ', '_').replace('-', '') + '.txt'
dictstr = myExtract(siteID)
myWriteFile(directory, filename, dictstr)
pendingtime = myWaiting(siteID, dictstr)
time.sleep(pendingtime)
although i dont know if this actually answers your question

Python - write() adding content I didn't expect

I am playing with the file I/O functions, and I am having issues writing to a file.
To get a feel for it, I have either run a FOR loop on a range, adding each to a new line, or done the same for a list. Either way, I get the following appended to the file after the loop:
98
99
is dropped.
"""
global quitting
try:
raise
except SystemExit:
raise
except EOFError:
global exit_now
exit_now = True
thread.interrupt_main()
except:
erf = sys.__stderr__
print>>erf, '\n' + '-'*40
print>>erf, 'Unhandled server exception!'
print>>erf, 'Thread: %s' % threading.currentThread().getName()
print>>erf, 'Client Address: ', client_address
print>>erf, 'Request: ', repr(request)
traceback.print_exc(file=erf)
print>>erf, '\n*** Unrecoverable, server exiting!'
print>>erf, '-'*40
quitting = True
thread.interrupt_main()
class MyHandler(rpc.RPCHandler):
def handle(self):
"""Override base method"""
executive = Executive(self)
self.register("exec", executive)
self.console = self.get_remote_proxy("console")
sys.stdin = PyShell.PseudoInputFile(self.console, "stdin",
IOBinding.encoding)
sys.stdout = PyShell.PseudoOutputFile(self.console, "stdout",
IOBinding.encoding)
sys.stderr = PyShell.PseudoOutputFile(self.console, "stderr",
IOBinding.encoding)
# Keep a reference to stdin so that it won't try to exit IDLE if
# sys.stdin gets changed from within IDLE's shell. See issue17838.
self._keep_stdin = sys.stdin
self.interp = self.get_remote_proxy("interp")
rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
def exithook(self):
"override SocketIO method - wait for MainThread to shut us down"
time.sleep(10)
<ad nauseum>
The code for creating this is:
f = open('test.txt', 'w+')
for x in range(100):
f.write((str(x) + '\n'))
f.read()
But even if I close it and open the file itself, this stuff is appended.
How can I just write the data to the file without this extra stuff?

Imported module logging calls not showing up

I have been reading up on proper logging and so far I am liking how it is going. All was fine until I tried to do logging in a main file and a module I wrote. The main file is able to write to a file and the console but the imported module displays nothing in either. If i had to take a guess, I am assuming I would have to configure the modules output separately as I am using in code configs. Problem is I am not sure how or if that is even the reason. I have tried my best to google this instead of asking but here I am now. Here is the link to the source code. If you try to run it you may have to change the import as pycharm does not like it when I import a file directly. So from "from tests import speedtest" to "import speedtest" The files are main.py and speedtest.py
Main
import logging
from tests import speedtest
import time
# Logging configuration
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# creates a handler to deal with writing to the file
file_handler = logging.FileHandler("log.txt", mode="w")
file_handler.setFormatter(logFormatter)
# handler for writing to the console
console_handler = logging.StreamHandler()
console_handler.setFormatter(logFormatter)
# adds the handlers to the root logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# max speed provided
NOMINAL_SPEED = 50
# threshold in percentage 60% seems to be a decent amount to expect.
THRESHOLD = 60
# padding in percentage for severe warning
PAD = 10
# amount of time in between runs
INTERVAL = 300
class Main:
"""
Main running class
"""
def __init__(self):
self.speedtest = speedtest.SpeedTest(share=True)
self.threshold = THRESHOLD
self.pad = PAD
self.nominal = NOMINAL_SPEED
self.done = False
logger.debug("Starting main loop.")
while not self.done:
self.loop()
time.sleep(INTERVAL)
def loop(self):
try:
results = self.speedtest.run()
except Exception as e:
logger.error("Skipped running speed test this run. Will try again next time")
return
download = float(results["download"][:-7])
upload = float(results["upload"][:-7])
url = results["url"]
host = results["host"]
diff_download = (download / self.nominal) * 100
logger.debug("Current download is {} Mbps upload is {} Mbps. Share url: {} host: {}".format(download, upload, url, host))
if (((self.threshold - self.pad)/100) * self.nominal) <= diff_download <= ((self.threshold/100) * self.nominal):
logger.info("Speed is currently at {}% nominal.".format(diff_download))
self.warning()
elif diff_download <= ((self.threshold - self.pad)/100) * self.nominal:
logger.info("Speed is currently at {}% nominal. This is a problem.".format(diff_download))
self.critical()
def warning(self):
pass
def critical(self):
pass
if __name__ == "__main__":
Main()
speedtest
import subprocess
import logging
import os
class SpeedTest:
"""
Class to run speed test and return the results in an easy to use manner
"""
def __init__(self, share=False):
"""
Init method
:param share: When set to true it will also return a url to the speed test image
:return:
"""
self.logger = logging.getLogger(__name__)
self.logger.addHandler(logging.NullHandler())
self._share = share
if share is True:
self.logger.debug("Share flag set to True")
self.cmd = ["speedtest-cli", "--share"]
else:
self.logger.debug("Share not set to true. Ignoring share url")
self.cmd = ["speedtest-cli"]
def run(self):
"""
Runs the speed test returning a dict containing upload, download, ping, and share url if wanted.
:return:
"""
self.logger.debug("Starting speedtest!")
# check_output returns the output in bytes so we use decode() to turn it into a simple string. Then we split
# the lines giving us a list.
try:
stdout = subprocess.check_output(self.cmd).decode().splitlines()
except subprocess.CalledProcessError as e:
self.logger.error(e)
raise e
res = {}
for i in stdout:
if "Download:" in i:
res["download"] = i[10:]
if "Upload:" in i:
res["upload"] = i[8:]
if "Hosted" in i:
res["host"] = i[2:]
if self._share is True and "Share results:" in i:
res["url"] = i[15:]
else:
res["url"] = None
return res
def ping(self, addr):
"""
Pings an address and returns a 1 if the connection can not be made or a 0 if it succeeds
:param addr: IPv4 address
:return:
"""
try:
if os.name is "nt":
self.logger.debug("Windows OS detected")
self.logger.info("Pinging {}".format(addr))
subprocess.check_output(["ping", "-n", "1", addr])
elif os.name is "posix":
self.logger.debug("Nix OS detected")
subprocess.check_output(["ping", "-c", "1", addr])
except subprocess.CalledProcessError:
self.logger.warning("Returned non zero value. Is the internet working?")
return 1
return 0
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
for i in SpeedTest(share=True).run().items():
print(i)
print(SpeedTest().ping("8.8.8.0"))
In speedtest.py when you call:
logging.getLogger(__name__)
it will create a logger object for speedtest.py, so you will have to configure it separately. If you want it to be the same logger as in the main just add:
self.speedtest.logger = logger
after you create the SpeedTest object in Main's constructor
Another option for you is to pass __name__ as an argument to SpeedTest() and create the logger with that argument (I think this is a better option for you since you write to the logger in the constructor).

Calling a thread out of scope in python

I have a thread that is defined as in a program that continuously reads serial data along with running a UI in wxpython.
dat = Thread(target=receiving, args=(self.ser,))
The method it calls "receiving" runs in an infinite loop
def receiving(ser):
global last_received
buffer = ''
while True:
date = datetime.date.today().strftime('%d%m%Y')
filename1 = str(date) + ".csv"
while date == datetime.date.today().strftime('%d%m%Y'):
buffer = buffer + ser.read(ser.inWaiting())
if '\n' in buffer:
lines = buffer.split('\n')
if lines[-2]:
last_received = lines[-2]
buffer = lines[-1]
print_data =[time.strftime( "%H:%M:%S"), last_received]
try:
with open(filename1, 'a') as fob:
writ = csv.writer(fob, delimiter = ',')
writ.writerow(print_data)
fob.flush()
except ValueError:
with open('errors.log','a') as log:
log.write('CSV file writing failed ' + time.strftime("%H:%M:%S")+' on '+datetime.date.today().strftime('%d/%m/%Y')+'\n')
log.close()
The argument is defined as
class SerialData(object):
def __init__(self, init=50):
try:
serial_list = serialenum.enumerate()
self.ser = ser = serial.Serial(
port=serial_list[0],
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=None,
xonxoff=0,
rtscts=0,
interCharTimeout=None
)
except serial.serialutil.SerialException:
# no serial connection
self.ser = None
else:
dat = Thread(target=receiving, args=(self.ser,))
if not dat.is_alive:
dat.start()
def next(self):
if not self.ser:
# return anything so we can test when Serial Device isn't connected
return 'NoC'
# return a float value or try a few times until we get one
for i in range(40):
raw_line = last_received
try:
return float(raw_line.strip())
time.sleep(0.1)
except ValueError:
# print 'Not Connected',raw_line
time.sleep(0.1)
return 0
Due to a bug in Ubuntu 14.04 the thread hangs after a while. I wanted to periodically check if the thread is alive and start it again if it is not. So I did something like
def on_timer(self):
self.text.SetLabel(str(mul_factor*self.datagen.next()))
if not dat.is_alive():
dat.start()
wx.CallLater(1, self.on_timer)
This runs every second to update the data in UI but also needs to check if the thread is not stopped. But this gives me an error saying "NameError: global name 'dat' is not defined". I also tried referring to the thread using the object name path. But didn't work either.
Can someone help me as to how I can start the thread out of scope?
It seems like you want to replace dat with self.dat. dat only exists in the scope of the __init__ method. I suggest reading up on Python scoping rules.

Python threading - Stopping a thread from another function

I've started playing with threading in python, after looking at lots of tutorials I finally have threading working in my project - however I've not found any examples where the thread is stopped from another function. So I can start the thread, it works fine, CSV is written correctly but I can't stop it. I get the following error from the stop function:
File "./blackboxv1.1.py", line 162, in stop_csv_logging
csv_thread.join()
NameError: global name 'csv_thread' is not defined
I've attached my code, it's only a snippet from much larger bit of code but everything is there I think should be relevant. The code essentially writes GPS data to a CSV file for logging GPS and accelerometer data, its called from a menu which calls the start and stop functions.
This bit in each function catches the key presses from the buttons on the LCD board and work fine.
sleep(0.5)
while 1:
if lcd.is_pressed(0):
break
else:
I'm fairly new to Python so this is a steep curve ..
class WriteCSV:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self):
# create unique filename based on date/time
new_file = time.strftime("%Y%m%d-%H%M%S.csv")
file_path = "/home/pi/scripts/gps/log_data/"
new_filename = file_path + new_file
# Set headers for csv
headers = ['TimeStamp', 'Speed', 'Lat', 'Lon', 'Alt', 'Climb', 'Acc_X', 'Accl_Y']
# needed to get accl data
accel = lsm.readAccelerationsG()
# create file and set headers then close
outfile = open(new_filename, 'a+')
writer = csv.writer(outfile)
writer.writerow(headers)
outfile.close()
while self._running:
# reopen existing file
outfile = open(new_filename, 'a+')
writer = csv.writer(outfile)
# unique timestamp needed for each row
time_stamp = time.strftime("%Y%m%d-%H%M%S")
# need to round down the g force numbers
accel.x = round(accel.x,1)
accel.y = round(accel.y,1)
# Set Row
row = [time_stamp, gpsd.fix.speed, gpsd.fix.latitude, gpsd.fix.longitude, gpsd.fix.altitude, gpsd.fix.climb, accel.x, accel.y]
# Write Row
writer.writerow(row)
# Close file
outfile.close()
# set sleep of 1 sec
sleep(1)
#========================================================
# Start CSV Logging
#========================================================
def start_csv_logging():
# create an instance of class WriteCSV
# create a thread using the instance
# then start the thread
sleep(0.5)
while 1:
if lcd.is_pressed(0):
break
else:
global csv_log
csv_log = WriteCSV()
# create the thread and start run()
csv_thread = threading.Thread(target=csv_log.run)
# start it up
csv_thread.start()
lcd.clear()
lcd.message("Starting Log ..")
sleep(2)
lcd.clear()
lcd.message("Logging!")
break
#========================================================
# Stop CSV Logging
#========================================================
def stop_csv_logging():
sleep(0.5)
while 1:
if lcd.is_pressed(0):
break
else:
# Signal termination
csv_log.terminate()
csv_thread.join()
# Wait for termination
lcd.clear()
lcd.message("Stopping ....")
sleep(2)
lcd.clear()
lcd.message("Log Stopped!")
sleep(2)
break
#========================================================

Categories

Resources