0

I have a script that watches for changes in file and if occurred it should trigger some actions. Those actions come from two functions defined outside Class. In Class I have defined portion of code to look for changes in file. I cannot figure out how to pass two functions in Class arguments. Here is simplified portion of my script:

import time, os

watch_file = 'my_file.txt'

def first_action():
    print('First action called')

def second_action():
    print('Second action called')

class Watcher():
    def __init__(self, watch_file, first_action=None, second_action=None):
        self._cached_stamp = 0
        self.filename = watch_file
        self.first_action = first_action
        self.second_action = second_action

    # Look for changes in 'my_file.txt'
    def look(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...
            print('File changed')
            if self.first_action is not None:
                print('Call first action')
                self.first_action(self)
            if self.second_action is not None:
                print('Call second action')
                self.second_action(self)    


watcher = Watcher(watch_file, first_action(), second_action())

Doing it like above calls first_action() and second_action() but not inside Class. I know it because I dont see printed 'Call first action' or 'Call second action' I was able to correctly trigger first action with below code:

watch_file = 'my_file.txt'

def first_action():
    print('First action called')

def second_action():
    print('Second action called')

class Watcher():
    def __init__(self, watch_file, first_action=None, *args):
        self._cached_stamp = 0
        self.filename = watch_file
        self.first_action = first_action
        self.args = args

    # Look for changes in 'my_file.txt'
    def look(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...
            print('File changed')
            if self.first_action is not None:
                print('Call first action')
                self.first_action(*self.args)    


watcher = Watcher(watch_file, first_action)

For some reason I need to specify *args even for function which does not take any argument on call. Can someone explain why *args must be used?

3
  • 1
    Typo. You mean watcher = Watcher(watch_file, first_action, second_action). Note that I'm not calling the functiosns. Commented Apr 6, 2020 at 13:58
  • 1
    You want to pass the functions themselves, not the return value of calling them. Watcher(watch_file, first_action, second_action). Commented Apr 6, 2020 at 13:58
  • I have already tried that and I only get "first_action" plus some error (see comment in DerHamm answer) Commented Apr 6, 2020 at 18:26

1 Answer 1

1

You did it right in the init, but not in the call of "Watcher". To pass the function itself, instead of it's return value, you have to remove the braces.

watcher = Watcher(watch_file, first_action, second_action)

And you should be fine.

Sign up to request clarification or add additional context in comments.

1 Comment

I have already tried that and I only get "first_action" plus some error: File changed Call first action Unhandled error: <class 'TypeError'> File changed Call first action Unhandled error: <class 'TypeError'>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.