Calling one method from another within same class in Python - python

I am very new to python. I was trying to pass value from one method to another within the class. I searched about the issue but i could not get proper solution. Because in my code, "if" is calling class's method "on_any_event" that in return should call my another method "dropbox_fn", which make use of the value from "on_any_event". Will it work, if the "dropbox_fn" method is outside the class?
I will illustrate with code.
class MyHandler(FileSystemEventHandler):
def on_any_event(self, event):
srcpath=event.src_path
print (srcpath, 'has been ',event.event_type)
print (datetime.datetime.now())
#print srcpath.split(' ', 12 );
filename=srcpath[12:]
return filename # I tried to call the method. showed error like not callable
def dropbox_fn(self)# Or will it work if this methos is outside the class ?
#this method uses "filename"
if __name__ == "__main__":
path = sys.argv[1] if len(sys.argv) > 1 else '.'
print ("entry")
event_handler = MyHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
The main issue in here is.. I cannot call "on_any_event" method without event parameter. So rather than returning value, calling "dropbox_fn" inside "on_any_event" would be a better way. Can someone help with this?

To call the method, you need to qualify function with self.. In addition to that, if you want to pass a filename, add a filename parameter (or other name you want).
class MyHandler(FileSystemEventHandler):
def on_any_event(self, event):
srcpath = event.src_path
print (srcpath, 'has been ',event.event_type)
print (datetime.datetime.now())
filename = srcpath[12:]
self.dropbox_fn(filename) # <----
def dropbox_fn(self, filename): # <-----
print('In dropbox_fn:', filename)

Related

QTextBrowser doesnt update with append, when calling this function from another class

Hello I have two function. One Class is a watchdog and the other class is a pyqt gui. I have three QTextBrowser.
If I connect a button to the function in the QT Class and call the function my TextBrowser get updated normally.
If I trigger an event in the watchdog and the watchdog class calls my QT class, my TextBrowser didnt update.
This is how I call the function from another class
class Handler(FileSystemEventHandler):
#staticmethod
def on_any_event(event):
if event.is_directory:
return None
elif event.event_type == 'created':
# Event is created, you can process it now
print("Watchdog received created event - % s." % event.src_path)
window = MyWindow()
window.start_xl()
This is the function, which works when i call it with a button.
def update(self):
terminate('cmd.exe')
terminate('EXCEL.exe')
self.text_Browser = self.ui.textBrowser
self.text_Browser_2 = self.ui.textBrowser_2
self.text_Browser_3 = self.ui.textBrowser_3
self.text_Browser.setTextColor(QtGui.QColor('white'))
self.text_Browser_2.setTextColor(QtGui.QColor('white'))
self.text_Browser_3.setTextColor(QtGui.QColor('white'))
path = "C:/Program Files (x86)/STIHL/Faps/Temp"
# Check if the folder is empty
if os.listdir(path):
# Get a list of all files in the directory
files = os.listdir(path)
# The first file in the directory
first_file = files[0]
self.text_Browser.append("FINISHED")
self.text_Browser_2.append("goal_dir")
self.text_Browser_3.append(first_file)
else:
self.ui.label.setText("Ordner ist Leer")
pass
This is the function which is called by the class Handler. Everything is working besides the updating of the TextBrowser
def start_xl(self):
terminate('cmd.exe')
terminate('EXCEL.exe')
self.text_Browser = self.ui.textBrowser
self.text_Browser_2 = self.ui.textBrowser_2
self.text_Browser.setTextColor(QtGui.QColor('white'))
self.text_Browser_2.setTextColor(QtGui.QColor('white'))
print(self.text_Browser)
print(self.text_Browser_2)
# QtCore.QMetaObject.invokeMethod(self.text_Browser, "append", QtCore.Qt.QueuedConnection,
# QtCore.Q_ARG(str, "FINISHED"))
# QtCore.QMetaObject.invokeMethod(self.text_Browser_2, "append", QtCore.Qt.QueuedConnection,
# QtCore.Q_ARG(str, "goal_dir"))
self.text_Browser.setPlainText("FINISHED")
# self.text_Browser_2.append("goal_dir")
I tried it with invoke and append. The kill process get started, so the function is called.
Is there something I should consider?

Python3: How to save data, when the destructor is called

I actually have a question on Python3. I want to save the attributes of a class in a file, when the destructor is called. How can I do that?
I tried to do it like this:
def __del__:
file = open("test.dat", "w")
file.write("Hello")
file.close()
That code doesn't work. I've already read, that you shouldn't use it, but I actually didn't find a alternative which works. Can anybody help me?
Thanks in advance!
to use that code it needs to be part of a class:
class Test():
def __init__(self):
self.data = "Hello"
def __del__(self):
with open('text.txt', mode='w') as file:
file.write(self.data)
if __name__ == '__main__':
def something():
obj = Test() # obj is deleted when function exits as it becomes out of scope
something()
obj = Test()
del obj # also works because we explicitly delete the object
note that while this method does work, it cannot always be relied upon to always be executed, for example if a sys.exit is called

Expecting Python assertRaises() to fail, but test always passes

I am attempting to get into the practice of TDD so I have been trying to start with Python's unittest module. I have written a test which I fully expect to fail, but it always passes! Below is the test code:
def test_file_not_found_exception(self):
invalid_config = "Testing/invalidExperiment.xml"
experiment_with_invalid_config = MyClass(invalid_config)
self.assertRaises(OSError, experiment_with_invalid_config.run_experiment())
and my class definition is as follows:
class MyClass:
def __init__(self, experiments, output_directory = ".")
self._experiments = experiments
self._output_directory = output_directory
def run_experiment(self):
try:
x = 2 # dummy statement
except OSError:
print "Experiment file not found"
except:
print "Unexpected Error"
I figure that the try block should always execute correctly so I am at a loss as to why my unittest keep passing. I am very new to OOP in Python so I may be making a very obvious mistake... Also, if I catch the exception in the try-except block of the run_experiment() method, should the assertRaises() call ever work?
You are calling the function MyClass.run_experiment and passing it's output to self.assertRaises, for which reason it does not properly register an error when it fails to raise.
Incorrect Example:
import unittest
class MyClass(object):
def __init__(self, config):
pass
def run_experiment(self): pass
class MainTest(unittest.TestCase):
def test_file_not_found_exception(self):
invalid_config = "Testing/invalidExperiment.xml"
experiment_with_invalid_config = MyClass(invalid_config)
self.assertRaises(OSError, experiment_with_invalid_config.run_experiment())
if __name__ == "__main__":
unittest.main()
Correct:
with self.assertRaises(OSError):
experiment_with_invalid_config.run_experiment()
Or
self.assertRaises(OSError, experiment_with_invalid_config.run_experiment)

python pyinotify to monitor the specified suffix files in a dir

I want to monitor a dir , and the dir has sub dirs and in subdir there are somes files with .md. (maybe there are some other files, such as *.swp...)
I only want to monitor the .md files, I have read the doc, and there is only a ExcludeFilter, and in the issue : https://github.com/seb-m/pyinotify/issues/31 says, only dir can be filter but not files.
Now what I do is to filter in process_* functions to check the event.name by fnmatch.
So if I only want to monitor the specified suffix files, is there a better way? Thanks.
This is the main code I have written:
!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyinotify
import fnmatch
def suffix_filter(fn):
suffixes = ["*.md", "*.markdown"]
for suffix in suffixes:
if fnmatch.fnmatch(fn, suffix):
return False
return True
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if not suffix_filter(event.name):
print "Creating:", event.pathname
def process_IN_DELETE(self, event):
if not suffix_filter(event.name):
print "Removing:", event.pathname
def process_IN_MODIFY(self, event):
if not suffix_filter(event.name):
print "Modifing:", event.pathname
def process_default(self, event):
print "Default:", event.pathname
I think you basically have the right idea, but that it could be implemented more easily.
The ProcessEvent class in the pyinotify module already has a hook you can use to filter the processing of events. It's specified via an optional pevent keyword argument given on the call to the constructor and is saved in the instance's self.pevent attribute. The default value is None. It's value is used in the class' __call__() method as shown in the following snippet from the pyinotify.py source file:
def __call__(self, event):
stop_chaining = False
if self.pevent is not None:
# By default methods return None so we set as guideline
# that methods asking for stop chaining must explicitly
# return non None or non False values, otherwise the default
# behavior will be to accept chain call to the corresponding
# local method.
stop_chaining = self.pevent(event)
if not stop_chaining:
return _ProcessEvent.__call__(self, event)
So you could use it only allow events for files with certain suffixes (aka extensions) with something like this:
SUFFIXES = {".md", ".markdown"}
def suffix_filter(event):
# return True to stop processing of event (to "stop chaining")
return os.path.splitext(event.name)[1] not in SUFFIXES
processevent = ProcessEvent(pevent=suffix_filter)
There's nothing particularly wrong with your solution, but you want your inotify handler to be as fast as possible, so there are a few optimizations you can make.
You should move your match suffixes out of your function, so the compiler only builds them once:
EXTS = set([".md", ".markdown"])
I made them a set so you can do a more efficient match:
def suffix_filter(fn):
ext = os.path.splitext(fn)[1]
if ext in EXTS:
return False
return True
I'm only presuming that os.path.splitext and a set search are faster than an iterative fnmatch, but this may not be true for your really small list of extensions - you should test it.
(Note: I've mirrored your code above where you return False when you make a match, but I'm not convinced that's what you want - it is at the very least not very clear to someone reading your code)
You can use the __call__ method of ProcessEvent to centralize the call to suffix_filter:
class EventHandler(pyinotify.ProcessEvent):
def __call__(self, event):
if not suffix_filter(event.name):
super(EventHandler, self).__call__(event)
def process_IN_CREATE(self, event):
print "Creating:", event.pathname
def process_IN_DELETE(self, event):
print "Removing:", event.pathname
def process_IN_MODIFY(self, event):
print "Modifying:", event.pathname

Python and indentation, having trouble getting started.

I have just started learning python and am getting caught up. I come from mostly C background.
class Alarm:
def timer():
def main():
print ("Timer has Started")
main()
I always get a silly error when I try to run this code:
alarm > python alarm.py
File "alarm.py", line 5
def main():
^
IndentationError: expected an indented block
You have an empty def
def timer():
use
def timer():
pass
instead.
Learn about the pass statement, main is usually not part of the class.
A global (module level) main() function is simpler than an Alarm.main() class method. Usually, main() functions come at module level.
class Alarm:
def timer():
pass
def main():
print ("Timer has Started")
main()
I think you want to use __init__ though, which is the constructor...
class Alarm:
def timer(self):
print('timer has started')
def __init__(self):
print('constructor')
self.timer()
x = Alarm()
constructor
timer has started
My example differs from the others in that I'm actually instantiating a new object.
Notes:
specify self as the first argument to any method defined in the class
__init__ is the method to define for the constructor
invoke the class by doing variableName = className() like you would invoke a function, no new keyword
if you have an empty function, use the pass keyword like def foo(self): pass
Invoking main() will give an undefined function error, as it is a Alarm method.
IMHO the right form you should use is the following:
class Alarm:
def timer():
pass
#staticmethod
def main():
print ("Timer has Started")
if __name__ == "__main__" :
Alarm.main()
try deindent main() and add pass to timer and define an init method:
class Alarm():
def __init__(self):
print ("Timer has Started")
<shell>$ Alarm()
Your timer function is not defined. (And your space/tab indentation may be mixed)
See the tutorial (classes) for more details on classes.
class Alarm:
def timer(self):
pass
def main(self):
print ("Timer has Started")
if __name__ == '__main__':
class_inst = Alarm()
class_inst.main()
If you getting into python read PEP8.
Also, using pylint helps, it will point out indentation and many other errors you'll run across before you 'execute' your code.
As others have pointed out, you have a syntax error because timer() has no body.
You don't need to use main() in python at all. Usually people use it to indicate that the file is the top level program and not a module to be imported, but it is just by convention
You may also see this idiom
def main():
blah blah
if __name__ == "__main__":
main()
Here __name__ is a special variable. If the file has been imported it will contain the module name, so the comparison fails and main does not run.
For the top level program __name__ contains "__main__" so the main() function will be run.
This is useful because sometimes your module might run tests when it is loaded as a program but you don't want those test to run if you are importing it into a larger program
In Python, you don't need to define everything as a class. There's nothing to encapsulate in this code, so there's no reason to define an Alarm class. Just have the functions in a module.
Thanks for all the help everybody. I was making a little alarm/timer to remind me to get up and take a walk every now and then. I got most of it working, and it works great. Checked it against a stop watch and it works great.
import time
def timer(num):
seconds = num*60
print (num , "minutes", seconds , "seconds")
while (seconds > 0):
print (seconds, "seconds")
time.sleep(1)
seconds = seconds-1
print ("Time to get up and take a WALK!!!!")
main()
def main():
number = input("Input time : ")
int(number)
timer(number)
if __name__ == '__main__':
main()

Categories