我有一个场景,我在运行时动态运行函数,需要跟踪“本地化”范围.在下面的示例中,“startScope”和“endScope”实际上将创建“嵌套”级别(实际上,此本地化作用域中包含的内容不是打印语句…它是在其他地方发送数据的函数调用和嵌套跟踪那里.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语句与上下文管理器实现类似的效果.在这里我使用
contextlib.contextmanager
装饰器:
@contextlib.contextmanager
def swallower():
try:
yield
except ZeroDivisionError:
print("We stopped zero division error")
def foo():
print("This error will be trapped")
with swallower():
print("Here comes error")
1/0
print("This will never be reached")
print("Merrily on our way")
with swallower():
print("This error will propagate")
nonexistentName
print("This won't be reached")
>>> foo()
This error will be trapped
Here comes error
We stopped zero division error
Merrily on our way
This error will propagate
Traceback (most recent call last):
File "
在您的示例中,无法使用普通函数调用.在您的示例中,函数startScope在myFunction的其余部分执行之前返回,因此startScope不会对它产生任何影响.要处理异常,你需要在myFunction内部使用某种显式结构(带语句或常规try / except);没有办法让一个简单的函数调用神奇地拦截在其调用者中引发的异常.
您应该阅读context managers,因为它们似乎符合您的要求.上下文管理器的__enter__和__exit__方法对应于startScope和endScope.它是否能完全满足您的需求取决于您希望这些“管理器”功能的确切要求,但是您可能会更幸运地使用上下文管理器而不是尝试使用简单的函数调用.