I am trying to use the ''watchdog'' package in python to monitor the change of my folder.
The following code are copied directly from the watchdog documentation, and it works fine.
import sys
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
path = '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=False)
observer.start()
try:
while observer.is_alive():
observer.join(1)
finally:
observer.stop()
observer.join()
However, when I tried to change the "path" variable, the code might not work.
For example, if path='./build/', I can see the changes in './build/' folder as expected, but if path='./build/result/', the terminal prints nothing no matter what changes I make to the corresponding folder.
I don't understand why, and I have to ask for help.
I am using ubuntu-20.04LTS through WSL2.
Related
There is the simplest script that shows when it was changed, but how do I get detailed information? For example, who changed it with reference to the directory.
`
import sys
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
path = sys.argv[1] if len(sys.argv) > 1 else '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while observer.isAlive():
observer.join(1)
finally:
observer.stop()
observer.join()
`
please with examples.
I looked at the manual on watchdog, but did not understand how to get this information.
The watchdog works via inotify mechanism and will only notify you that a file had been changed, created or deleted. There is no information in the filesystem about who did the change. The information you have is basically the same information that you would get by looking at a directory listing such as with ls -al.
Assuming you are working on Linux, a file has an owner and a group. Typically, they are set according to the UID/GID of a process that creates the file, and remain unchanged even if a process with another UID/GID modifies the file (unless explicitly changed with chmod/chgrp).
To track filesystem changes in more detail, you probably need to use the audit subsystem, but that's a completely different story.
I wanted to detect changes in certain directories, and if I heard changes in the files, for example, many changes at the same time it would return some print and perform certain actions. (I'm programming for linux)
import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == '__main__':
# Set the format for logging info
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# Set format for displaying path
#path = sys.argv[1] if len(sys.argv) > 1 else '.'
path = '/home/kali/Downloads'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
I'm using this base code to perform the actions, but how can I put the conditions of several changes using this base?
The python code below is my first attempt for notification when a file is modified, however nothing happens when the file is changed.
What have I missed here?
#!/usr/bin/python3
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class MyHandler(FileSystemEventHandler):
def on_modified(self, event):
print('file changed')
if __name__ == "__main__":
event_handler = MyHandler()
observer = Observer()
observer.schedule(event_handler, path='/Users/jeff/smb/storage/wsjt-x/wsjtx_log.adi', recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
NOTE: I found that this code works well using Linux. It's on macOS Big Sur where I'm having issues.
After clarifying your environment in comments, one of following 3 approaches might resolve your issue.
Reproduction: Watching a local file on Linux
Running in one shell A and meanwhile using another shell B to add to the observed file so.md like:
echo "---" >> so.md
results in following output:
python3 so_watchdog.py so.md
file changed <FileModifiedEvent: event_type=modified, src_path='so.md', is_directory=False>
file changed <DirModifiedEvent: event_type=modified, src_path='', is_directory=True>
Here is the slightly modified version of your script (see comments):
#!/usr/bin/python3
import time
import sys
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class MyHandler(FileSystemEventHandler):
def on_modified(self, event):
print('file changed', event) # added event to see the difference of two events for a single modification
if __name__ == "__main__":
if len(sys.argv) < 2:
file = '/Users/jeff/smb/storage/wsjt-x/wsjtx_log.adi'
else:
file = sys.argv[1]
# below only added the file as path
event_handler = MyHandler()
observer = Observer()
observer.schedule(event_handler, path=file, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Note: This was tested on Linux, with a local file.
Watching shared files (CIFS/SMB)
Since your path /Users/jeff/smb/storage/wsjt-x/wsjtx_log.adi contains smb I assume, you are watching a file on a mounted shared network location using the SMB (Server Message Blocks) protocol, also known as CIFS (Common Internet File System).
Then please follow the official documentation, About using watchdog with CIFS:
When you want to watch changes in CIFS, you need to explicitly tell watchdog to use PollingObserver, that is, instead of letting watchdog decide an appropriate observer like in the example above, do:
from watchdog.observers.polling import PollingObserver as Observe
So your import statement needs to be modified.
Watching files locally on MacOS
For MacOS the underlying file-system event API used is FSEvents or FreeBSD's kqueue, instead of Linux's inotify.
Thus the behavior might also deviate.
I don't want to enable linux onedrive service as I've noticed it can be hard on my cpu, so I would rather run it on demand. That's why I'm trying to create a little script that would run onedrive sync one time only when I access OneDrive directory. Makes sense? I hope so.
I thought it would be easy but watchdog doesn't seem to have a way to monitor for that kind of event. Is there any other way I could do this ? Am I missing something ?
Here is watchdog documentation:
https://python-watchdog.readthedocs.io/en/v0.10.2/quickstart.html#a-simple-example
import sys
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
path = sys.argv[1] if len(sys.argv) > 1 else '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while observer.isAlive():
observer.join(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
I'm running linux mint 19 in case it matters.
A good utility for executing actions when some files change is entr.
For example if you'd like to run some script upload_to_onedrive.sh every time a file changes in the directory onedrive you'd just ls ~/onedrive | entr ./upload_to_onedrive.sh
I am trying to use Python Watchdog to monitor a directory for changes. However, when I try to run the Quickstart example:
import time
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path='.', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
by putting in it the file test.py, nothing displays in the Terminal window where I ran it. What is causing this to happen, and how can I fix it?
Try the example on github: https://github.com/gorakhargosh/watchdog
This example seems to work as opposed to the one on the docs site that does not.