如何在从主函数调用的函数中检测错误情况



我有一个小程序,它从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中处理错误的标准方法是引发异常:

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(。这种行为通常是可取的,因为通常如果发生错误,你不想继续做你正在做的事情。

如果出于某种原因,即使f1已经产生错误,您也希望调用f2,那么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)

使用global几乎是在函数之间传递信息的最佳方式。对于最简单的情况之外的任何情况,它只会使您的代码非常难以调试。

我建议创建一个ERROR_COUNTERint变量或字典来存储计数,比如:

{ functionname: count, functionname2: count }

每次出现错误时都会更新。

从函数内部生成变量global并不好。

我不知道你的具体用例/上下文,但如果每个函数调用只执行一个操作,你也可以在每个函数调用中返回一个int错误。这将使调用者负责处理错误计数,而不是单个函数。

我赞同其他人在这里提出的观点,即提出异常是对错误的适当响应,但如果您需要特定的错误行为,请添加嵌入try/except循环:

def a():
if random.randint(0, 9) == 0:
raise Exception("error!")
def main():
f = Path('/var/tmp/error_triggered/' + os.path.splitext(os.path.basename(__file__))[0])
try:
for i in range(0,5):
a()
f.unlink(missing_ok=True)
except Exception as e:
print(e)
f.touch()

我假设你的代码比随机引发错误要复杂一些,但原理是一样的——如果有东西命中并出错,它应该引发一个异常,如果你需要以一种不仅仅是离开外壳的方式处理异常,请使用try/except循环。

最新更新