Is it possible to create a dynamic localized scope in Python? -
i have scenario i'm dynamically running functions @ run-time , need keep track of "localized" scope. in example below, "startscope" , "endscope" creating levels of "nesting" (in reality, stuff contained in localized scope isn't print statements...it's function calls send data elsewhere , nesting tracked there. startscope / endscope set control flags used start / end current nesting depth).
this works fine tracking nested data, however, exceptions matter. ideally, exception result in "falling out" of current localized scope , not end entire function (myfunction in example below).
def startscope(): #increment our control object's (not included in example) nesting depth control.incrementnestingdepth() def endscope(): #decrement our control object's (not included in example) nesting depth control.decrementnestingdepth() def myfunction(): print "a" print "b" startscope() print "c" raise exception print "d" print "this print statement , previous 1 won't printed" endscope() print "e" def main(): try: myfunction() except: print "error!"
running (theoretically) output following:
>>> main() b c error! e >>>
i'm quite isn't possible i've written above - wanted paint picture of sort of end-result i'm trying achieve.
is possible in python?
edit: more relevant (albeit lengthy) example of how being used:
class log(object): """ log class """ def __init__(self): #datamodel defined elsewhere , contains 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 logger import log def test_alpha(): """ crazy contrived example in example, there 2 levels of nesting...everything startadvanced(), , after endadvanced() included in top level...everything between 2 contained in separate level. """ log.warning("better careful here!") log.adddatapoint(fancymath()[0]) data = getserialdata() if data: log.info("got data, let's continue advanced test...") log.startadvanced() #note: if breaks in 1 of following methods, goto (***) operateondata(data) dosomethingcrazy(data) log.todo("fill in more stuff here later...") log.adddatapoint(data) log.endadvanced() #(***) ideally, resume here if exception raised in above localized scope log.info("all done! log data , wrap up!") log.adddatapoint({"data": "blah"}) #done #framework.py import inspect logger import log class framework(object): def __init__(self): print "framework init!" self.tests = [] def loadtests(self, file): """ simplifying sake of clarity """ test in file: self.tests.append(test) def runtests(self): """ simplifying sake of clarity """ #test_alpha() other user tests run here test in self.tests: log.starttest() try: test() except exception,e : log.error(str(e)) log.endtest() #end
you can achieve similar effect context manager using with
statement. here use contextlib.contextmanager
decorator:
@contextlib.contextmanager def swallower(): try: yield except zerodivisionerror: print("we stopped 0 division error") def foo(): print("this error trapped") swallower(): print("here comes error") 1/0 print("this never reached") print("merrily on our way") swallower(): print("this error propagate") nonexistentname print("this won't reached") >>> foo() error trapped here comes error stopped 0 division error merrily on our way error propagate traceback (most recent call last): file "<pyshell#4>", line 1, in <module> foo() file "<pyshell#3>", line 10, in foo nonexistentname nameerror: global name 'nonexistentname' not defined
it cannot done ordinary function call in example. in example, function startscope
returns before rest of body of myfunction
executes, startscope
can't have effect on it. handle exceptions, need kind of explicit structure (either with
statement or regular try/except
) inside myfunction
; there's no way make simple function call magically intercept exceptions raised in caller.
you should read on context managers seem fit you're trying do. __enter__
, __exit__
methods of context manager correspond startscope
, endscope
. whether want depends on want "manager" functions do, have more luck doing context manager trying simple function calls.
Comments
Post a Comment