首页 > 解决方案 > 如何检测从主函数调用的函数中的错误情况?

问题描述

我有一个小程序,它从main()函数中调用多个函数,并且在每个函数中发生错误的概率很小。为了与现有的监控系统兼容,/var/tmp/error_triggered/如果至少有一个错误,我需要将文件制作到目录中,如果没有错误,我需要从该目录中删除文件。一种方法是使用具有全局范围的变量:

#!/usr/bin/env python3

import os
import random
from pathlib import Path

def f1():
  global error
  for i in range(1, 5):
    if random.randint(0, 9) == 0:
      error = 1

def f2():
  global error
  for i in range(1, 5):
    if random.randint(0, 9) == 0:
      error = 1

def main():
  f1()
  f2()

if __name__ == '__main__':
  error = 0
  main()
  if error == 1:
    Path('/var/tmp/error_triggered/' + os.path.splitext(os.path.basename(__file__))[0]).touch()
  else:
    Path('/var/tmp/error_triggered/' + os.path.splitext(os.path.basename(__file__))[0]).unlink(missing_ok=True)

从函数内部修改全局变量通常是一种不好的做法。这里合理吗?或者有没有更好的方法来解决这个问题?

标签: python

解决方案


在 Python 中处理错误的标准方法是引发异常:

def f1():
    for i in range(1, 5):
        if random.randint(0, 9) == 0:
            raise ValueError()

def f2():
    for i in range(1, 5):
        if random.randint(0, 9) == 0:
            raise ValueError()

def main():
    f = Path('/var/tmp/error_triggered/' + os.path.splitext(os.path.basename(__file__))[0])
    try:
        f1()
        f2()
        f.unlink(missing_ok=True)
    except ValueError:
        f.touch()

这与您所做的事情之间存在细微差别:如果f1引发异常,f2则不会被调用(也就是说,引发异常会立即停止try块并直接转到except)。这往往是可取的行为,因为通常如果发生错误,您不想继续您正在做的事情。

如果出于某种原因f2即使f1已经产生错误也希望被调用,那么它可能更适合return错误,就像您返回任何其他值一样:

def f1():
    for i in range(1, 5):
        if random.randint(0, 9) == 0:
            return 1
    return 0

def f2():
    for i in range(1, 5):
        if random.randint(0, 9) == 0:
            return 1
    return 0

def main():
    f = Path('/var/tmp/error_triggered/' + os.path.splitext(os.path.basename(__file__))[0])
    if f1() + f2():
        f.touch()
    else:
        f.unlink(missing_ok=True)

使用 aglobal几乎从来都不是在函数之间传递信息的最佳方式。除了最简单的情况之外,它只会使您的代码非常难以调试。


推荐阅读