Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

Will an error in a Python Script Action stop a Macro?

If you have a question or need help, this is the place to be.
Post Reply
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

Does anyone know if I have a Python Script in the middle of a macro and there is an Unhandled error within the Python Script will it stop the Macro from continuing or will the actions after the Python Script action still run?
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Will an error in a Python Script Action stop a Macro?

Post by kgschlosser »

good question. i believe it will. but i could be wrong. never really thought about it. but with how the code for a macro is run in the same thread i believe it will.. but it will also cause that thread to terminate causing more then just the macro to stop running. because the macro is not run in a thread of it's own. (again this is all an I think. I would have to look at the code)
If you like the work I have been doing then feel free to Image
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

Thanks for the quick reply! I would very much like to know for sure. And if that's the case I wish there were a way to allow the macro to continue even after an error within the Python Script action. For some reason I feel like I read somewhere that Python Script actions are executed within their own thread and not the Macros, but I could also be wrong.

Below is the code I have in the Python Script action

Code: Select all

import shutil
import os
import stat

def remove_readonly(func, path, excinfo):
    os.chmod(path, stat.S_IWRITE)
    func(path)

#os.chmod is used to turn off Read-Only attribute
os.chmod("Q:/Setup.vbs", stat.S_IWRITE)
#os.remove is used to remove individual files
os.remove("Q:/Setup.vbs")

#shutil.rmtree is used to remove entire directories
#remove traces of file
shutil.rmtree("Q:/My Resources", onerror=remove_readonly)
shutil.rmtree("Q:/Me", onerror=remove_readonly)
shutil.rmtree("C:/Documents/Project Development", onerror=remove_readonly)
I was hoping to avoid having to wrap every single action in it's own error handler (to report which specific command fails, should any of them fail) and just be able to see which line of the Python Script the error occurred by looking at the EG log, then rest easy knowing the rest of my macro also ran. Do you have any advice how I should go about the situation? Is there anyway to allow this sort of behavior to allow errors to be ignored (but still logged in EG)?
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
topix
Experienced User
Posts: 441
Joined: Sat May 05, 2007 3:43 pm
Location: Germany
Contact:

Re: Will an error in a Python Script Action stop a Macro?

Post by topix »

For a simple test put somewhere in your (working) script a

Code: Select all

raise ValueError
and see what happens.
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

This is the result when adding the line you suggested. The OSD action did run, so I guess that means that the macro does continue to run, right? How could I incorporate that into my actual script posted in my earlier comment?

Image
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
topix
Experienced User
Posts: 441
Joined: Sat May 05, 2007 3:43 pm
Location: Germany
Contact:

Re: Will an error in a Python Script Action stop a Macro?

Post by topix »

Yes, looks like the macro continues(, but not the script). What do you mean with "incorporate that into my actual script"?
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

Is there a way for me to use the `raise ValueError` in my script so that the error that occurs in the Python Script action is logged in the EG log while the rest of the Python Script action also tries to continue? I want to be able to know if any of the commands in the python script cause an error, but I want the rest of the script to run through to perform as many of the actions in the python script that it can. Is that possible? I'm not quite sure how to set that up in python. Doesn't it have something to do with

Code: Select all

try: 

except: 

finally:
I don't know how to make my python script continue if there is an error.

So, to summarize, I'm trying to:
  • Have the Python Script try every single command in it, continuing onto all the commands below any command that causes an error while logging the error in EG Log
  • Have the Macro continue after the Python Script errors (which I believe we've already figured out that it will)
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
topix
Experienced User
Posts: 441
Joined: Sat May 05, 2007 3:43 pm
Location: Germany
Contact:

Re: Will an error in a Python Script Action stop a Macro?

Post by topix »

Ah, ok. I think thats not possible inside a python script action. Because in the moment the exception is shown in the log, the script is already stopped (only the [python] script [action], not the whole macro where the python script action belongs to). So you would need to use try/except.
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

Okay, so I've taken some time to tweak my Python Script action to the following.

First Python Script Action:

Code: Select all

import shutil
import os
import stat

def remove_readonly(func, path, excinfo):
    os.chmod(path, stat.S_IWRITE)
    func(path)

try:
    #os.chmod is used to turn off Read-Only attribute
    os.chmod("Q:/-----.vbs", stat.S_IWRITE)
    #os.remove is used to remove individual files
    os.remove("Q:/-----.vbs")
except:
    pass

#shutil.rmtree is used to remove entire directories
#remove traces of file
try:
    shutil.rmtree("Q:/FolderToRemove1", onerror=remove_readonly)
except:
    pass

try:
    shutil.rmtree("Q:/FolderToRemove2", onerror=remove_readonly)
except:
    pass

try:
    shutil.rmtree("Q:/FolderToRemove3", onerror=remove_readonly)
except:
    pass

try:
    shutil.rmtree("Q:/FolderToRemove4", onerror=remove_readonly)
except:
    pass

try:
    shutil.rmtree("Q:/FolderToRemove5", onerror=remove_readonly)
except:
    pass

try:
    shutil.rmtree("C:/Users/mhill/Desktop/screenshots", onerror=remove_readonly)
except:
    pass
Then once that's down, two actions later I check to see if the paths were successfully removed with the following

Second Python Script Action:

Code: Select all

import os

#Test if directories still exists
eg.globals.PDEVdirectory = os.path.exists("C:/DeletedDirectory1")
eg.globals.PubESPAdirectory = os.path.exists("Q:/DeletedDirectory2")
eg.globals.PubASIRdirectory = os.path.exists("Q:/DeletedDirectory3")
eg.globals.DWNLDSdirectory = os.path.exists("C:/DeletedDirectory4")
eg.globals.DOCSdirectory = os.path.exists("C:/DeletedDirectory5")
eg.globals.SCRNSHTSdirectory = os.path.exists("C:/DeletedDirectory6")

#Print results to log
if not eg.globals.PDEVdirectory:
    print 'PDEV directory successfully scrubbed'
else:
    print 'PDEV directory scrub failed'
    

if not eg.globals.PubESPAdirectory:
    print 'PubESPA directory successfully scrubbed'
else:
    print 'PubESPA directory scrub failed'
    

if not eg.globals.PubASIRdirectory:
    print 'PubASIR directory successfully scrubbed'
else:
    print 'PubASIR directory scrub failed'
    

if not eg.globals.DWNLDSdirectory:
    print 'DWNLDS directory successfully scrubbed'
else:
    print 'DWNLDS directory scrub failed'
    

if not eg.globals.DOCSdirectory:
    print 'DOCS directory successfully scrubbed'
else:
    print 'DOCS directory scrub failed'
      

if not eg.globals.SCRNSHTSdirectory:
    print 'SCRNSHTS directory successfully scrubbed'
else:
    print 'SCRNSHTS directory scrub failed'
Will this work? I'm not familiar with all the mechanics of python functions, so I don't know if I'm able to use a `shutil.rmtree` command that has an `onerror` function defined within a try/except block and have the try/except block's except run. But, looking at the documentation (source: https://docs.python.org/dev/library/shutil.html) for the `shutil.rmtree` command it states
...to remove a directory tree on Windows where some of the files have their read-only bit set. It uses the onerror callback to clear the readonly bit and reattempt the remove. Any subsequent failure will propagate.
Correct me if I'm wrong, but this to me sounds like the `onerror` function will run once if a `shutil.rmtree` command errors, then when the command is trying to re-run after its `onerror` function runs it will raise the error once again, this time not triggering the `onerror` function. So, would the error trigger its corresponding `except` block then? That's what I took it as, which is why I tweaked the code as I did above. Can anyone confirm that this is how the programmatic flow will work? Also, can anyone confirm that the above code will work for what I'm trying to accomplish?
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Will an error in a Python Script Action stop a Macro?

Post by kgschlosser »

sure there is a way...



with EG there is always a way!!!



ok so you will do this at each point where you think there could be a potential error.


i am going to give you an example code here

Code: Select all


import traceback

test_a = [1, 2, 4, 5, 6, 7]
test_b = [1, 2, 3]
testdict = {}

try:
    if test_a[0] == 1 and test_b[3] == 4:
        try:
            if test_a[20] == 5:
                test = None
        except IndexError:
            traceback.print_exc()
except IndexError:
    traceback.print_exc()

try:
    print textDict['test']
except KeyError:
    traceback.print_exc()
this is pseudo code and i have not run it at all.

but this shows what exception catching is or what is known as "duck typing"
it's easier to ask forgiveness for doing something and it's wrong then it is to ask for permission.. LOL


but when an exception is raised for doing something wrong you can "catch" it with try, except
now there are many different error types

StopIteration - Raised when the next() method of an iterator does not point to any object.
SystemExit - Raised by the sys.exit() function.
StandardError - Base class for all built-in exceptions except StopIteration and SystemExit.
ArithmeticError - Base class for all errors that occur for numeric calculation.
OverflowError - Raised when a calculation exceeds maximum limit for a numeric type.
FloatingPointError - Raised when a floating point calculation fails.
ZeroDivisonError - Raised when division or modulo by zero takes place for all numeric types.
AssertionError - Raised in case of failure of the Assert statement.
AttributeError - Raised in case of failure of attribute reference or assignment.
EOFError - Raised when there is no input from either the raw_input() or input() function and the end of file is reached.
ImportError - Raised when an import statement fails.
KeyboardInterrupt - Raised when the user interrupts program execution, usually by pressing Ctrl+c.
LookupError - Base class for all lookup errors.
IndexError - Raised when an index is not found in a sequence.
KeyError - Raised when the specified key is not found in the dictionary.
NameError - Raised when an identifier is not found in the local or global namespace.
UnboundLocalError - Raised when trying to access a local variable in a function or method but no value has been assigned to it.
EnvironmentError - Base class for all exceptions that occur outside the Python environment.
IOError - Raised when an input/ output operation fails, such as the print statement or the open() function when trying to open a file that does not exist. and also Raised for operating system-related errors.
SyntaxError - Raised when there is an error in Python syntax.
IndentationError - Raised when indentation is not specified properly.
SystemError - Raised when the interpreter finds an internal problem, but when this error is encountered the Python interpreter does not exit.
SystemExit - Raised when Python interpreter is quit by using the sys.exit() function. If not handled in the code, causes the interpreter to exit. and Raised when Python interpreter is quit by using the sys.exit() function. If not handled in the code, causes the interpreter to exit. and Raised when an operation or function is attempted that is invalid for the specified data type.
ValueError - Raised when the built-in function for a data type has the valid type of arguments, but the arguments have invalid values specified.
RuntimeError - Raised when a generated error does not fall into any category.
NotImplementedError - Raised when an abstract method that needs to be implemented in an inherited class is not actually implemented.

now you do not have to specify an exceptionand can just do

Code: Select all

try:
except:
but this is really not good form and it will catch all exceptions, even ones you may not want it to.

you can also group the exceptions together

Code: Select all

try:
except (KeyError, IndexError, ValueError):
and if my chance you want to catch the exception and do some code and then raise the exception

Code: Select all

try:
except KeyError:
    # do some code here then raise the same exception
    raise
or if you want to run it way later on down the line

Code: Select all

try:
    test = boo[1]
    err = None
except KeyError as err:
    test = none

if err:
    raise err
and exception handling can be used in just about everywhere in python code

Code: Select all

try:
    import test_import
    do some code here....
except ImportError:
     do different code here

this is nice because if someone doesn't have a specific library, it doesn't halt the code.

if you have any questions fire away
If you like the work I have been doing then feel free to Image
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Will an error in a Python Script Action stop a Macro?

Post by kgschlosser »

and i do have a question for you i notice you are putting all the os.path queries into globals. are the globals used elsewhere in your tree??? some other script??

because if not it doesn't have to be eg.globals.VARNAME it can be just VARNAME
If you like the work I have been doing then feel free to Image
User avatar
caffeinatedcoder
Posts: 20
Joined: Wed Jul 06, 2016 4:56 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by caffeinatedcoder »

Wow, that seems like a lot to remember at this moment. Since I already have an edited version of my code, is there any way you could give me some feedback on how that would perform? I mean, I don't need it to be top-of-the-line code as long as it'll get the job done for this one action.
pro┬Àgram┬Àmer (n) An organism capable of converting caffeine into code.
User avatar
kgschlosser
Site Admin
Posts: 5190
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Will an error in a Python Script Action stop a Macro?

Post by kgschlosser »

this is untested. so give it a shot. it would be a type if it doesn't work. the idea behind how it's coded is sound.

i commented it like crazy so you can get a better understanding of what is going on. and that is actually the bulk of the code. you do not have to leave the comments in there if you don't want to.

enjoy

K

Code: Select all

from os import path

DELETED_PATH = 'c:\\DeletedDirectory%d'
ATTR_NAMES = [ 'PDEV', 'PubESPA ',  'PubASIR',  'DWNLDS',  'DOCS', 'SCRNSHTS']

# since the directory is a constant and the only thing that changes is
# the number on the end of the path we can iterate through a list of the eg.global names
# and use that to count which index we are on my using the enumerate
# we do have to add one to the index number because a list index starts at 0,
#  and the directories start at 1 
for i, attrName in enumerate(ATTR_NAMES):

    # Test if directories still exists adding that number onto the end + 1
    attr = path.exists(DELETED_PATH % i + 1)

    # Create the eg.globals attribute since the end of the variable name is the same
    # we don't have to have that in our list of names we add it here
    setattr(eg.globals, attrName + 'directory', attr)

    # now we do out check to see if it was sucessful or not and instead of printing i decided to
    # trigger an event. just in cause you wanted to do something if it succeeded or failed.
    if attr:
        suffix = '%s.SuccessfullyScrubbed'
    else:
        suffix = '%s.FailedBeingScrubbed'
    eg.TriggerEvent(prefix='Directory', suffix=suffix % attrName) 

If you like the work I have been doing then feel free to Image
m19brandon
Experienced User
Posts: 177
Joined: Mon Feb 03, 2014 10:36 pm

Re: Will an error in a Python Script Action stop a Macro?

Post by m19brandon »

I like to set EG.result none at the start of all my macros and then set it true or false in my Python Scripts and then check the state through out my macros. This prevents and stops the macros as needed. I now also know I made mistake because my end action never completes.
krambriw
Plugin Developer
Posts: 2570
Joined: Sat Jun 30, 2007 2:51 pm
Location: Stockholm, Sweden
Contact:

Re: Will an error in a Python Script Action stop a Macro?

Post by krambriw »

Another way of running python scripts that I prefer is to use the built in eg.scheduler. If you schedule a python function call (instead of immediate execution) it will run in a separate thread. I gave example here in another topic
http://eventghost.net/forum/viewtopic.p ... 020#p43004
Post Reply