File Monitoring using watchdog library - python

I have written one python script to monitor one local folder which is having only .txt files and i want to start this script automatically if some changes happened to the folder(created,deleted or updated)
I tried to run this script and also tried to make changes in the directory, but i couldn't see any output and no error messages. It always says "Process finished with exit code 0" can any one review my code and give me some tips where to correct to get the expected out put.
import os
import sys
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
#Step 1 Create the event handler
if __name__ == "__main__":
patterns = ".txt"
ignore_patterns = None
ignore_directories = False
case_sensitive = True
event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)
#step 2 Handle all the events
def on_created(event):
print("new files has been created!")
def on_deleted(event):
print("Some files has been Deleted")
def on_modified(event):
print("Some files has been modified")
def on_moved(event):
print("Some files has been moved")
#step 3 specify to the handler that we want these functions to be called
event_handler.on_created = on_created
event_handler.on_deleted = on_deleted
event_handler.on_modified = on_modified
event_handler.on_moved = on_moved
#step 4 create an observer
path = "T:\Laboratory\Instruments\Worklists\TrackMateRacks\old"
go_recursively = True
my_observer = Observer()
my_observer.path(event_handler, path, recursive=go_recursively)
# start the observer
my_observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
my_observer.stop()
my_observer.join()

you have to move the lines after " # start the observer" to the very left.
otherwise there will be executed nothing. that lines are part of on_moved(). but you want them to be executed if you start the script.
or
for most programs it's useful to add this line:
if __name__ == '__main__':
bevore line "# start the observer"
than your my_observer.start() will be executed, if you call your script. but if you import your script in another script, this will not be executed, but the other script can use all the functions, you created.

It seems, that you're really new to Python. You've to watch the indents, they're part of the syntax.
Exceptionally I reformat the complete code for you:
import os
import sys
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
#Step 1 Create the event handler
patterns = ".txt"
ignore_patterns = None
ignore_directories = False
case_sensitive = True
event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)
#step 2 Handle all the events
def on_created(event):
print("new files has been created!")
def on_deleted(event):
print("Some files has been Deleted")
def on_modified(event):
print("Some files has been modified")
def on_moved(event):
print("Some files has been moved")
#step 3 specify to the handler that we want these functions to be called
event_handler.on_created = on_created
event_handler.on_deleted = on_deleted
event_handler.on_modified = on_modified
event_handler.on_moved = on_moved
#step 4 create an observer
def main():
path = "T:\Laboratory\Instruments\Worklists\TrackMateRacks\old"
go_recursively = True
my_observer = Observer()
my_observer.path(event_handler, path, recursive=go_recursively)
# start the observer
my_observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
my_observer.stop()
my_observer.join()
if __name__ == "__main__":
main()
#end of file
Good luck!

Related

Python subprocess.Popen not stop when using kill()

I am trying to restart a python process, when file changes are made.
Dir Structure
/root
|_ test.py
|_ main.py
main.py
import os
import sys
import shutil
import _thread
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler, FileSystemEvent
cwd = os.getcwd()
pj = os.path.join
exists = os.path.exists
class Reloader(FileSystemEventHandler):
def __init__(self, openProc: subprocess.Popen = None, cmd=""):
super().__init__()
self.__cmd = cmd
self.openProc = openProc if openProc else subprocess.Popen(self.__cmd, cwd=cwd, shell=True)
def on_any_event(self, event):
if event.is_directory:
return
_, ext = os.path.splitext(event.src_path)
if ext[1:] in ["py", "cpp", "c", "h", "hpp"]:
print(":: CHANGES DETECTED, RELOADING ::")
print("--changed file '{}'--".format(event.src_path))
self.killProc()
def killProc(self):
self.openProc.kill()
def getInput():
global cwd
cwd = os.getcwd()
return input("⚡>" + cwd + ">")
if __name__ == "__main__":
while True:
userInput = getInput()
split = userInput.split(" ")
print("Starting CMD Command With Reloader...")
while True:
try:
event_handler = Reloader(cmd=split)
observer = Observer()
observer.schedule(event_handler, cwd, recursive=True)
observer.start()
while event_handler.openProc.poll() is None:
pass
observer.stop()
except KeyboardInterrupt:
break
test.py
import time
c = 0
while True:
c+=1
print(c)
time.sleep(1)
When I run that:
E:\electrocli>py main.py
⚡>E:\electrocli>py test.py
Starting CMD Command With Reloader...
1
2
3
4
:: CHANGES DETECTED, RELOADING ::
--changed file 'E:\electrocli\test.py'--
:: CHANGES DETECTED, RELOADING ::
--changed file 'E:\electrocli\test.py'--
5
1
6
2
7
3
This shows that, the older process, whis should be revoked by subprocess.Popen.kill has not ended. I want to kill the old process, and start the new one. Is there any way to do that? Or, is there any mistake in my code?

watchdog in directory monitoring is not working

I want to watch a folder for addition, modification and deletion of file and execute a command whenever any of this event occurs.
I found this tutorial that helped https://www.michaelcho.me/article/using-pythons-watchdog-to-monitor-changes-to-a-directory
so here is the code I now have
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Watcher:
DIRECTORY_TO_WATCH = "/Users/***/desktop/google drive/protpics"
def __init__(self):
self.observer = Observer()
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.DIRECTORY_TO_WATCH, recursive=True)
self.observer.start()
try:
while True:
time.sleep(5)
except:
self.observer.stop()
print("Error")
self.observer.join()
class Handler(FileSystemEventHandler):
#staticmethod
def on_my_event(event):
if event.is_directory:
return None
elif event.event_type == 'created':
#Take any action here when a file is first created.
print ("Recived created event - %s" % event.src_path)
elif event.event_type == 'modified':
# Take any action here when a file is modified.
print ("Recieved modified event - %s" % event.src_path)
if __name__ == '__main__':
W = Watcher()
W.run()
the problem now is that when I added a new file to the directory no message gets printed out. What am I doing wrong and how can I fix it?
Couldn't you figure out the difference between your code and example's? In your link, the author use on_any_event, but you are using on_my_event. There isn't a method named on_my_event.
Have a check at official document: http://pythonhosted.org/watchdog/api.html#watchdog.events.FileSystemEventHandler

Send file pointer to python thread and update file pointer

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.

Python watchdog for files from two different directories

I am trying to listen to filesystem changes using the watchdog module of Python. I want to monitor the files from two different directories. For a single file watch, I used PatternMatchingEventHandler from watchdog.events. I want to use the same for multiple directories.
code:
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class EventHandler(PatternMatchingEventHandler):
def on_modified(self, event):
super(EventHandler, self).on_modified(event)
print event
if __name__ == "__main__":
dir_name = ["/home/user1/first", "/home/user1/second"]
observer = Observer()
patterns = ["/home/user1/first/first.log","/home/user1/second/second.log")]
for i in xrange(len(dir_name)):
event_handler = EventHandler(patterns = patterns[i])
observer.schedule(event_handler, dir_name[i], recursive=True)
observer.start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
observer.stop()
In the above code, I tried to do multiple directory observing format and create an event handler for each of the files. It's not working for me. Is there anything that I am missing here?? What is the way to do this??
Thanks.
some wrong in here
EventHandler(patterns = patterns[i])
arg patterns is a type of list, so you can use like this
patterns = [["/home/user1/first/first.log"], ["/home/user1/second/second.log"]]
EventHandler(patterns = patterns[i])
Though it does not use the watchdog library , this will the easy way just to check if the specific type of files are added or removed
if u want to check which files u can append them using any variable and store them in array
import os
import fnmatch
import threading
import time
initial_count = 0
flag = 0
files = []
path = ["/home/kirti/workspace/pythonproject6/img", "/home/kirti/workspace/pythonproject6/copy"]
def taskcount(path, flag, initial_count):
while 1:
time.sleep(3)
new_count = len(fnmatch.filter(os.listdir(path), "*.jpg"))
if new_count > initial_count:
if flag != 0:
print("Added \nCount :", new_count, "=", path)
else:
print(new_count)
if new_count < initial_count:
print("Removed \nCount :", new_count, "=", path)
initial_count = new_count
flag = 1
for j in range(len(path)):
t = threading.Thread(target=taskcount, args=(path[j], flag, initial_count))
t.start()
I am using python3, LINUX OS
With a minor modification as suggested above and some additions from myside too this is working now
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class EventHandler(PatternMatchingEventHandler):
def on_modified(self, event):
super(EventHandler, self).on_modified(event)
print(event)
if __name__ == "__main__":
dir_name = ["/home/don/test1", "/home/don/test2"]
observer = Observer()
threads=[]
patterns = [['*.log'],['*.ok']]
for i in range(len(dir_name)):
event_handler = EventHandler(patterns = patterns[i],ignore_directories=True,case_sensitive=False)
observer.schedule(event_handler, dir_name[i], recursive=True)
threads.append(observer)
observer.start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Comparing with mine, you are lacking of observer.join() at the EOF. Try with that.
EDIT
Try this code below:
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class EventHandler(PatternMatchingEventHandler):
def on_modified(self, event):
super(EventHandler, self).on_modified(event)
print event
if __name__ == "__main__":
observer = Observer()
patterns = ["/home/user1/first/first.log","/home/user1/second/second.log"]
for pattern in patterns:
event_handler = EventHandler(patterns=pattern)
observer.schedule(event_handler, dir_name[i], recursive=True)
observer.start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
observer.stop()
observer.join()

How to pass an argument to my Python watchdog.events.PatternMatchingEventHandler

I'm quite new to Python and hope the answer to this is obvious to most of you.
I'm creating a class in Python that represents a ScanFolder.
In the __init__ of that class, I start a watchdog.observers
This observer will fire a watchdog.events.PatternMatchingEventHandler whenever a file is changed under the watched directory.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import time
from watchdog.observers import Observer
import watchdog.events
path = sys.argv[1] if len(sys.argv) > 1 else '.'
class MyEventHandler(watchdog.events.PatternMatchingEventHandler):
def on_any_event(self, event):
print(event.src_path, event.event_type)
class ScanFolder:
'Class defining a scan folder'
def __init__(self, path):
self.path = path
self.documents = dict() # key = document label value = Document reference
self.event_handler = MyEventHandler(patterns=["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.pdf"],
ignore_patterns=[],
ignore_directories=True)
self.observer = Observer()
self.observer.schedule(self.event_handler, self.path, recursive=False)
self.observer.start()
def stop(self):
self.observer.stop()
self.observer.join()
scan_folder = ScanFolder(path)
try:
while True:
time.sleep(1)
"""Here, I'll act on my scan_folder object that lists the discovered files"""
except KeyboardInterrupt:
log.warning("Ouch !!! Keyboard interrupt received.")
scan_folder.stop()
My problem is the following:
How can I have my scan_folder object modified by my scan_folder.event_handler() ?
Actually, I would like to populate the scan_folder.documents dictionary wherever a file is detected in the scan folder.
Thank you very much and sorry for my ignorance.
There are a lot of way to do it: but the simplest way is set a bound method of ScanFolder as on_any_event callback function of watchdog.events.PatternMatchingEventHandler. So your code become:
class ScanFolder:
'Class defining a scan folder'
def __init__(self, path):
self.path = path
self.documents = dict() # key = document label value = Document reference
self.event_handler = watchdog.events.PatternMatchingEventHandler(patterns=["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.pdf"],
ignore_patterns=[],
ignore_directories=True)
self.event_handler.on_any_event = self.on_any_event
self.observer = Observer()
self.observer.schedule(self.event_handler, self.path, recursive=False)
self.observer.start()
def on_any_event(self, event):
print(event.src_path, event.event_type)
print("Complete ScanFolder() access")
def stop(self):
self.observer.stop()
self.observer.join()
Other way could be derive ScanFolder from watchdog.events.PatternMatchingEventHandler .... But injecting function is one of the power of python

Categories