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

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -