re-using the variable in a function in a class in python - python

I will try to explain the problem I am facing with a small piece of code:
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.csv","*.processing", "*.transforming","*.loading"]
def process(self, event):
eventFileName = event.src_path
eventType = event.event_type
if eventType == 'moved':
eventFileName = event.dest_path
fileNameWithPath, fileExtension = os.path.splitext(eventFileName)
if fileExtension == '.processing':
# Here some function is called to do something, and then appends ".loading" to the file name
testVariable = 75.3
if fileExtension == '.loading':
print testVariable
def on_moved(self, event):
self.process(event)
def on_created(self, event):
self.process(event)
if __name__ == '__main__':
observer = Observer()
observer.schedule(MyHandler(), path='.')
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
When I try to do the above I am getting this error: global name 'testVariable' is not defined which kinda makes sense but how do I make the above work? I tried to define "testVariable" globally and initiated to 0 and tried using it the way I showed in above code but it did not work as well.
I also tried initiating testVariable as testVariable=0 inside the class (right after "patterns = ....." line but I got this error: local variable "testVariable" referenced before assignment pointing towards print testVariable. So that didnot work as well.

"(...) how do I make the above work?"
By defining testVariable outside your conditional statements. E.g. here:
def process(self, event):
eventFileName = event.src_path
testVariable = 0
...
This will make it available within the process function. If you want it to be available throughout the class, you can define it here:
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.csv","*.processing", "*.transforming","*.loading"]
testVariable = 0
But then you have to access it via the self object within functions like so:
def process(self, event):
...
if fileExtension == '.processing':
# Here some function is called to do something, and then appends ".loading" to the file name
self.testVariable = 75.3

testVariable only exists if you have the extension ".processing". If it's ".loading", the program tries to print a variable that hasn't been made to exist.
If statements do not create a garbage collecting scope in Python, so you don't have to "declare" it outside, so long as somewhere in your if-tree, tesVariable gets a value.

def process(self, event):
def extension():
eventFileName = event.src_path
eventType = event.event_type
if eventType == 'moved':
eventFileName = event.dest_path
return os.path.splitext(eventFileName)[1]
if extension() == '.processing':
...
if extension() == '.loading':
...

Related

Python pass a global variable when the script reloads

So I am trying to pass a global variable when the script reloads with a click of a button. The problem is that when the script loads the global variable is again empty. How can I solve this issue? Will I need a second .py file? Basically I am trying to pass a folder path when the script reloads.
Thank you.
# Global variable
folder_path = ''
class TestDialog(QtWidgets.QDialog):
def __init__(self, folder_path_arg ,parent=maya_main_window()):
super(TestDialog, self).__init__(parent)
self.setWindowTitle('HDRI Browser')
self.setMinimumWidth(430)
self.setMaximumWidth(430)
self.setMinimumHeight(500)
self.setMaximumHeight(500)
self.create_widgets()
self.create_connections()
print( "printing in TestDialog: "+ str(folder_path) )
# (...)
def show_folder_selected_dialog(self):
selected_folder_dialog = QtWidgets.QFileDialog()
sel_dir = selected_folder_dialog.getExistingDirectory(self, 'Select a folder')
if sel_dir:
self.filepath_le.setText(sel_dir)
# SET Global variable folder_path
listOfGlobals = globals()
listOfGlobals['folder_path'] = self.filepath_le.text()+str('/')
def load_folder_selected_dialog(self):
from importlib import reload
import hdri_browser_script_v1
reload(hdri_browser_script_v1)
if __name__ == "hdri_browser_script_v1":
try:
test_dialog.close()
test_dialog.deleteLater()
except:
pass
# passing the variable folder_path as argument
test_dialog = TestDialog(folder_path)
test_dialog.show()

Watchdog ignore pattern

I tried working with other posts on here about this, but couldn't get it to work. I'm a newbie with Python.
I need help with ignore_pattern.
I'm uploading images to a folder and temporarily images are being added with __, so the actual image added while file is uploading is __image-name.jpg. After it's done uploading it gets added again as image-name.jpg (and deletes the __image-name.jpg.
I want to ignore all the __image-name.jpg files with watchdog.
Here's my code:
class Watcher:
DIRECTORY_TO_WATCH = "director/where/images/are/uploaded"
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_any_event(event):
if event.is_directory:
return None
elif event.event_type == 'created':
# Take any action here when a file is first created.
print(event.src_path)
img = Image.open(event.src_path)
for result in engine.classify_with_image(img, top_k=3):
print('---------------------------')
print(labels[result[0]])
print('Score : ', result[1])
# elif event.event_type == 'modified':
# Taken any action here when a file is modified.
# print("Received modified event - %s." % event.src_path)
elif event.event_type == 'deleted':
# Taken any action here when a file is deleted.
print("Received deleted event - %s." % event.src_path)
if __name__ == '__main__':
w = Watcher()
w.run()
Thank you so much.
Does event.src_path returns a string? If so you can use the startswith method of the string class to skip over the images you don't want.
For example:
elif event.event_type == 'created':
# Take any action here when a file is first created.
print(event.src_path)
# Check if this filename starts with "__" and execute the next block
if not event.src_path.startswith('__'):
img = Image.open(event.src_path)
for result in engine.classify_with_image(img, top_k=3):
print('---------------------------')
print(labels[result[0]])
print('Score : ', result[1])
# else do nothing

Python - call multiple external functions in Class instance

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?
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.

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.

Categories