'How to watch the file change and compare the two files in python?

I have a requirement where I need to do the following:

  1. Watch a file for any changes - done

  2. Compare the file with the changed file - pending

    • That means, say I have a text file with the content "hello world" as below:

hello.txt

hello world

Then I will add another line to the same file as below

hello world
some other line

up on the save, it should create a new file without actually writing to the same file so, I should end up with two files instead of one:

  1. hello.txt - original file
hello world
  1. hello_modified.txt - modified (appended) file
hello world
some other

How can I do this with python ?

I have already used watchdog for listening to file modification, I have even implemented the function to display the diff between the two files too. But I have no idea how to write the logic for the file replication. i.e. how can I create and write to another file up on saving the hello.txt without really saving the hello.txt ?



Solution 1:[1]

I think you can do this by using a while loop and time module. Note that, reading a file each time a while statements loops over itself, is probitively expensive for your computer processor. So, in this answer, I decided to check the files every 3 seconds.

from time import time

startTime = time()
diffTime = 3
with open("hello.txt") as f:
  checkFile = f.read()
while True:
  now = time()
  if now > startTime+diffTime:
    startTime = now
    with open("hello.txt") as f:
      myString = f.read()
    if checkFile != myString:
      with open("hello_modified.txt", "w") as f:
        f.write(myString)
      with open("hello.txt", "w") as f:
        f.write(checkFile)

Solution 2:[2]

Here's an implementation using a coroutine file_copier. See usage and test for usage.

import itertools
from pathlib import Path
import shutil

def copy(src: Path, dst: Path):
    print(f"Copying {src} to {dst}")
    shutil.copyfile(src, dst)

def file_copier(watched_path: str|Path):
    if isinstance(watched_path, str):
        watched_path = Path(watched_path)

    shutil.copyfile(watched_path, watched_path.with_stem(f'{watched_path.stem}_0'))

    for counter in itertools.count():
        yield
        copy(watched_path, watched_path.with_stem(f'{watched_path.stem}_{counter+1}'))
        copy(watched_path.with_stem(f'{watched_path.stem}_{counter}'), watched_path)



path = Path("hello.txt")

def usage():
    fc = file_copier(path)
    next(fc)    # start/init

    # When 'hello.txt' has been modified:
    next(fc)    # copies 'hello.txt' to new history file and resets 'hello.txt' to previous history file



# TEST

def create():
    """Creates empty 'hello.txt'"""
    with open(path, "w") as f:
        pass

def append(line: str):
    """Simulates modification of 'hello.txt'"""
    with open("hello.txt", "a") as f:
        print(line, file=f)

def test():
    fc = file_copier(path)

    create()
    append("hello world")
    next(fc)

    append("edit 1")
    next(fc)

    append("edit 2")
    next(fc)

    append("edit 3")
    next(fc)


if __name__ == '__main__':
    test()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Amirhossein Kiani
Solution 2