我有一个在运行时动态运行函数的场景,需要跟踪“本地化”范围。在下面的示例中,“startScope”和“endScope”实际上是在创建“嵌套”级别(实际上,这个本地化范围中包含的内容不是print语句……而是函数调用,它们将数据发送到其他地方,并在那里跟踪嵌套)。startScope/endScope(仅设置用于开始/结束当前嵌套深度的控制标志)。你知道吗
这些都可以很好地跟踪嵌套数据,但是,异常是另一回事。理想情况下,异常将导致“脱离”当前的本地化范围,而不是结束整个函数(下面示例中的myFunction)。你知道吗
def startScope():
#Increment our control object's (not included in this example) nesting depth
control.incrementNestingDepth()
def endScope():
#Decrement our control object's (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!"
运行此操作(理论上)会产生以下结果:
>>> main()
A
B
C
Error!
E
>>>
我很确定这是不可能的,因为我已经写在上面了-我只是想画一幅画的那种最终结果,我正在努力实现。你知道吗
在Python中这样做可能吗?你知道吗
编辑:一个更相关(尽管很长)的示例,说明如何实际使用它:
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's 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
使用} 装饰器:
with
语句使用上下文管理器可以获得类似的效果。这里我使用^{这不能像你的例子那样用普通的函数调用来完成。在您的示例中,函数
startScope
在myFunction
主体的其余部分执行之前返回,因此startScope
对它没有任何影响。要处理异常,需要在myFunction
内部使用某种显式结构(一个with
语句或一个常规的try/except
);无法让一个简单的函数调用神奇地截获调用方中引发的异常。你知道吗你应该仔细阅读context managers,因为它们似乎适合你要做的事情。上下文管理器的
__enter__
和__exit__
方法将对应于您的startScope
和endScope
。“使用函数调用时,您是否希望使用这些函数来做什么,可能更取决于您是否希望使用函数调用来做什么”。你知道吗相关问题 更多 >
编程相关推荐