在Python中检测缩进

4
def divide(x, y): 
    try: 
        # Floor Division : Gives only Fractional Part as Answer 
        result = x // y 
        print("Yeah ! Your answer is :", result) 
    except ZeroDivisionError: 
        print("Sorry ! You are dividing by zero ")

    try: 
        result = x // y 
        print("Yeah ! Your answer is :", result) 
    except: 
        print("An error occurred") 

    try: 
        # Floor Division : Gives only Fractional Part as Answer 
        result = x // y 
        print("Yeah ! Your answer is :", result) 
    except ZeroDivisionError: 
        print("Sorry ! You are dividing by zero ")
    except NameError: 
        print("Name Error")
    except MemoryError: 
        print("Memory Error")
    except AttributeError: 
        print("Here is some\
            long long error message\
            .....")

我有一个包含三个 try...except 子句的函数。我的目标是检测它有多少个独立的 try...except 子句(在这个函数中是3个),以及每个子句中有多少 except 关键字(第一个和第二个各有1个,第三个有4个)。

我尝试通过执行以下代码来导入此文件

with open("test.py", "r") as f:
    content = f.readlines()
    ... # getting each line

尝试通过检测缩进级别来分割try...except子句。 然而,我觉得这不是一种全面的方法,可能有更简单的方法。

需要帮助吗?


3
我不完全清楚你想做什么,但是看一下 ast模块。实际上,解析代码并在内存数据结构中处理它可能比从原始文本中猜测更好。 - Chris
没有明确的方法来查看是否存在无用的 try...except 语句块。我正在尝试检测它们。 - Dawn17
1
你如何定义“无用”的try...except子句? - sanyassh
@Sanyash 两种无用的异常:1)只有一个except子句并捕获太一般的异常,如Exception和Standard Error,2)语句中的所有异常子句都为空。 - Dawn17
@Sanyash 1) 标准错误只是一个没有错误的except(在我的问题中是第二个try...except子句)。2)是的。 - Dawn17
显示剩余2条评论
1个回答

3
这是使用 ast 开始你任务的一个起点。通过你的代码示例,它检测到第12行的 except 没有任何异常并打印出了 过于笼统的 except,第12行。我还测试了 except Exception:,消息是相同的,而且使用 except ZeroDivisionError: pass,消息是无用的 except。你可以拿来进一步改进(与模块中的几个函数一起使用等)。
import ast

with open('test.py') as f:
    data = f.read()
    module = ast.parse(data)
    function = module.body[0]
    for obj in function.body:
        if isinstance(obj, ast.Try):
            try_block = obj
            for handler in try_block.handlers:
                if handler.type is None:
                    print('too broad except, line {}'.format(handler.lineno))
                    continue
                if handler.type == 'Exception':
                    print('too broad except, line {}'.format(handler.lineno))
                    continue
                if len(handler.body) == 1 and isinstance(handler.body[0], ast.Pass):
                    print('useless except, line {}'.format(handler.lineno))

对于您在问题中提到的目标(统计每个try...except块和每个块中的except子句的数量),很容易实现,如下所示:len([obj for obj in function.body if isinstance(obj, ast.Try)])len(try_block.handlers)


这很令人印象深刻。非常感谢!不过我有几个问题。在 function = module.body[0]for obj in function.body: 这两行中,body 表示什么?另外,在 https://docs.python.org/2.4/lib/module-compiler.ast.html 中,似乎 ast 中的每个节点类型都有不同的属性。这会影响如何检测 Python 中特定的关键字吗? - Dawn17
无法回答你的第二个问题,对于第一个问题,我只能给你展示这个链接:https://docs.python.org/3/library/ast.html#abstract-grammar。`body` 可以是一些东西的列表,其中每个元素可以是一个函数、返回语句、尝试语句等,或者它可以是一个单独的表达式。对于你的模块,在 module.body 中只有一个元素——它就是你的函数(根据文档是 FunctionDef),在函数中有三个 try 语句(Try)。此外,你可以检查 handler.body 并查看那里的语句列表。 - sanyassh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接