I have a scenario in which I dynamically execute functions at runtime and need to track the "localized" area. In the example below, "startScope" and "endScope" will actually create levels of "nesting" (in fact, the material contained in this localized area is not print instructions ... these are function calls that send data elsewhere, but nesting tracked there.startScope / endScope just sets the control flags that are used to start / end the current nesting depth).
This all works great for tracking nested data, but exceptions are another matter. Ideally, an exception will cause the current localized scope to βdrop outβ rather than terminate the entire function (myFunction in the example below).
def startScope(): #Increment our control object (not included in this example) nesting depth control.incrementNestingDepth() def endScope(): #Decrement our control object (not included in this example) nesting depth control.decrementNestingDepth() def myFunction(): print "A" print "B" startScope() print "C" raise Exception print "D" print "This print statement and the previous one won't get printed" endScope() print "E" def main(): try: myFunction() except: print "Error!"
Running this will (theoretically) output the following:
>>> main() A B C Error! E >>>
I am absolutely sure that this is impossible, because I wrote it above - I just wanted to paint a picture of the final result that I am trying to achieve.
Is something like this possible in Python?
Edit: A more appropriate (albeit long) example of how this is used:
class Log(object): """ Log class """ def __init__(self): #DataModel is defined elsewhere and contains a bunch of data structures / handles nested data / etc... self.model = DataModel() def Warning(self, text): self.model.put("warning", text) def ToDo(self, text): self.model.put("todo", text) def Info(self, text): self.model.put("info", text) def StartAdvanced(self): self.model.put("startadvanced") def EndAdvanced(self): self.model.put("endadvanced") def AddDataPoint(self, data): self.model.put("data", data) def StartTest(self): self.model.put("starttest") def EndTest(self): self.model.put("endtest") def Error(self, text): self.model.put("error", text) #myScript.py from Logger import Log def test_alpha(): """ Crazy contrived example In this example, there are 2 levels of nesting...everything up to StartAdvanced(), and after EndAdvanced() is included in the top level...everything between the two is contained in a separate level. """ Log.Warning("Better be careful here!") Log.AddDataPoint(fancyMath()[0]) data = getSerialData() if data: Log.Info("Got data, let continue with an advanced test...") Log.StartAdvanced() #NOTE: If something breaks in one of the following methods, then GOTO (***) operateOnData(data) doSomethingCrazy(data) Log.ToDo("Fill in some more stuff here later...") Log.AddDataPoint(data) Log.EndAdvanced() #(***) Ideally, we would resume here if an exception is raised in the above localized scope Log.Info("All done! Log some data and wrap everything up!") Log.AddDataPoint({"data": "blah"}) #Done #framework.py import inspect from Logger import Log class Framework(object): def __init__(self): print "Framework init!" self.tests = [] def loadTests(self, file): """ Simplifying this for the sake of clarity """ for test in file: self.tests.append(test) def runTests(self): """ Simplifying this for the sake of clarity """ #test_alpha() as well as any other user tests will be run here for test in self.tests: Log.StartTest() try: test() except Exception,e : Log.Error(str(e)) Log.EndTest() #End