题
采用此代码:
def A():
try:
B()
except Exception:
pass
def B():
C()
def C():
print exception_handling_pointer()
A()
功能 exception_handling_pointer
应将我的指针返回到该功能的指针,以便首先检查此特定异常以进行处理。即,在这种情况下,我希望输出为STH。像:
<function A ...>
如何实现该功能 exception_handling_pointer
?
解决方案
这是一件非常愚蠢的事情,大多数人会说这是不可能的(THC4K给出了一般的CACE的令人信服的证据),但听起来确实很有趣,并且在许多真实用例中都应该完全可行。
第1步. 。您需要退后一步。获得第一个 sys._getframe
或者 inspect.currentframe
(不要告诉任何人,第二个似乎是在第一个混音的)。然后,您可以通过他们迭代 f.f_back
第2步. 。每个人都会有一个 f.f_lasti
操作说明。这是帧中执行的最后一个指令。您必须保存它。现在通过字节码进行后字 - f.f_code.co_code
- 寻找 SETUP_EXCEPT
opcode的参数跳到 后 f.f_lasti`。跳跃点是例外处理。
步骤3. 。这就是它变得更加模糊的地方。关键是实际的比较操作将是 COMPARE_OP
以10为论点。在我看过的所有情况下,随后是 POP_JUMP_IF_FALSE
. 。这将跳到下一个 except
条款或 finally
条款。在此之前,它将加载将异常加载到堆栈上。如果只有一个,那将是一条 LOAD_GLOBAL
或a LOAD_GLOBAL
或者 LOAD_FAST
(取决于异常的模块是全局还是本地的),然后是 LOAD_ATTR
. 。如果有多个异常匹配,则将有一系列负载操作,然后是 BUILD_TUPLE
(惯用)或 BUILD_LIST
(其他一些怪异或非异教的情况)。
关键是您可以通过 LOAD_X
说明并将名称与您要匹配的例外进行比较。请注意 仅比较名称. 。如果他们重新分配了名称,那么您是SOL。
第4步. 。假设您找到了一场比赛。现在您需要功能对象。我能想到的最好的方法如下(我保留更新的权利): f.f_code
将有一个 co_filename
属性。你可以循环 sys.modules
每个人都会有 __name__
属性。您可以比较两者,请记住您应该使用的 __name__.endswith(co_filename)
. 。当您获得比赛时,您可以在模块功能上循环并比较它们的 f.func_code.co_firstlineno
带有帧的属性 f.f_lineno
属性。当您获得比赛时,您会拥有您的功能。您也应该在模块中的每个类的方法上循环。在某些嵌套功能中,处理方法可能会发生,在这种情况下,我目前无法想到一件明智的事情。 (这将是另一个横幅hack,本身会是薄弱的)
步骤5. 。利润。
这应该为您提供有关如何执行此操作的一般想法。在各种角落的情况下,您都无法执行此操作,但是在任何普通用例中,您都应该能够将其删除。如果您编写取决于能够做到的代码, 将要 虽然休息。这是一种“做到这一点,因为我可以”有点东西。
其他提示
您无法决定如果不实际提出例外,将在哪里处理。这很容易在这里看到:
try:
raise input('Raise which?')
except input('Catch which?') as e:
pass`
任何执行您想要的功能都必须在此处预测用户输入。整个努力都是徒劳的,Python没有支持。
无论如何,我希望你只问出于兴趣...