Python 清理嵌套的Try/Excepts

Python 清理嵌套的Try/Excepts,python,Python,我刚刚写了一段代码,这段代码给我的印象是嵌套远远超过了最佳嵌套。我想听听关于如何改进这种样式的建议,特别是让它更符合“扁平优于嵌套” 编辑: 结合下面的建议,这是我重写的表格。 for app in apps: if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps continue try: a = app + '.cron' __import__(a)

我刚刚写了一段代码,这段代码给我的印象是嵌套远远超过了最佳嵌套。我想听听关于如何改进这种样式的建议,特别是让它更符合“扁平优于嵌套”

编辑: 结合下面的建议,这是我重写的表格。

for app in apps:
    if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps
        continue

    try:
        a = app + '.cron'
        __import__(a)
    except ImportError: #no cron jobs for this module, continue to next one
        continue

    m = sys.modules[a]
    if hasattr(m, 'cron_minute'):
        min = m.cron_minute()
        for job in min:
            k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB),
                                60*job[1], 
                                kronos.method.threaded, (), ())

    if hasattr(m, 'cron_hour'):
        hour = m.cron_hour()
        for job in hour:
            k.add_daytime_task(job[0], 'day task', range(1, 8), None,
                               (job[1], r(H_LB, H_UB)), 
                               kronos.method.threaded, (), ())

您可以创建一个执行主逻辑的函数,以及另一个调用该函数的函数,并用try…except语句包装它。然后,在主应用程序中,您可以只调用那些已经处理异常的函数。(根据《清洁代码》一书中的建议)。

好吧,这里的诀窍是找出它们是否被破坏。这是异常处理的部分。我的意思是,至少打印一条警告,说明评论的假设。在实际操作之前担心过多的嵌套似乎是在超越自己。在时尚之前先担心是否正确。

主要问题是你的try子句太宽泛,尤其是最外层的:有了这种习惯,你迟早会遇到一个神秘的bug,因为你的try/except中有一个意外隐藏了一个异常“冒泡”从您正在调用的其他函数

因此,我建议:

for app in apps:
    if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps
        continue

    try:
        a = app + '.cron'
        __import__(a)
    except ImportError: #no cron jobs for this module
        continue

    # etc etc
另一方面,我还以另一种方式(不依赖于任何尝试/例外)应用了“flat优于nested”,即“如果我在循环的这一段上没有更多的事情要做,请继续[即移动到循环的下一段],而不是“如果我有事情要做:“然后是大量嵌套代码。我一直更喜欢这种风格(if/continue或if/return),而不是在提供功能的语言中嵌套if,如
continue
(基本上都是现代的,因为C有;-)


但这是一个简单的“扁平vs嵌套”风格偏好,问题的核心是:保持try子句的小!最糟糕的情况是,当您不能简单地在except子句中继续或返回时,您可以使用try/except/else:只在try子句中输入绝对必须存在的内容——可能出现并预期会出现的一小段代码——并在else子句中输入以下代码的其余部分(不应该也不希望出现的部分)。这不会改变嵌套,但会在降低意外隐藏意外异常的风险方面起到巨大的作用

我想知道,如果每一个时间单位的工作都被打破了,他们会不会引起一个态度错误,或者其他一些例外?特别是,如果一份工作真的出了什么问题,你很可能会发现它们

另一个有帮助的选项是使用try-catch仅包装有问题的代码,将异常处理程序尽可能地放在异常附近。这里有一个刺:

for app in apps:
    if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps
        try:
            a = app + '.cron'
            __import__(a)
            m = sys.modules[a]
        except ImportError: #no cron jobs for this module
                            #exception is silently ignored
                            #since no jobs is not an error
            continue
        if hasattr(m, "cron_minute"):
            min = m.cron_minute()
            for job in min:
                k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB),
                                    60*job[1], 
                                    kronos.method.threaded, (), ())

        if hasattr(m, "cron_hour"):
            hour = m.cron_hour()
            for job in hour:
                k.add_daytime_task(job[0], 'day task', range(1, 8), None,
                                   (job[1], r(H_LB, H_UB)), 
                                   kronos.method.threaded, (), ())
请注意,这里只有一个异常处理程序,我们通过正确忽略它来处理它。 因为我们可以预测不存在一个或另一个属性的可能性,所以我们 明确地检查它,这有助于使代码更加清晰。否则就不是了
很明显,为什么你会发现AttributeError,或者是什么引起了它

您误解了代码的作用。如果捕获到异常,它应该什么也不做——如果正在检查的东西不存在,这不是错误(事实上,在大多数情况下,它们不会)。我不希望为未找到的可选函数的每个实例打印警告。此代码只被调用一次。我可以编写几个函数来实现它,但这实际上只是生成意大利面代码,而不是实际改进布局。谢谢,这正是我所需要的。我忘了用这种方式继续。你关于尽量减少尝试的建议是有道理的。使用continue允许我这样做。它在重写的形式中更加明确。啊,谢谢!在这里使用hasattr()比try/except更简洁。
for app in apps:
    if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps
        try:
            a = app + '.cron'
            __import__(a)
            m = sys.modules[a]
        except ImportError: #no cron jobs for this module
                            #exception is silently ignored
                            #since no jobs is not an error
            continue
        if hasattr(m, "cron_minute"):
            min = m.cron_minute()
            for job in min:
                k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB),
                                    60*job[1], 
                                    kronos.method.threaded, (), ())

        if hasattr(m, "cron_hour"):
            hour = m.cron_hour()
            for job in hour:
                k.add_daytime_task(job[0], 'day task', range(1, 8), None,
                                   (job[1], r(H_LB, H_UB)), 
                                   kronos.method.threaded, (), ())