采用此代码:

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没有支持。

无论如何,我希望你只问出于兴趣...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top