我有一个小程序,它从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_COUNTER
int变量或字典来存储计数,比如:
{ 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循环。