0
点赞
收藏
分享

微信扫一扫

loguru在工程日志中的应用


1.Python的logging模块中的error和exception区别**

共同点:

logging模块有6个级别,由低到高为​​NOTSET>>DEBUG>>INFO>>WARNING>>ERROR>>CRITICAL​​​,其实无论是​​error​​​还是​​exception​​,它们的错误等级都是ERROR级别。

from loguru import logger
try:
port, minimum = 10, 12
assert port >= minimum
except Exception as e:
logger.error(e)
logger.exception(e)

运行结果为:

2022-03-04 23:52:13.925 | ERROR    | __main__:<module>:11 - 
2022-03-04 23:52:13.927 | ERROR | __main__:<module>:12 -

我们可以看到日志信息中,错误等级都是ERROR

不同点:

error级别的只输出错误的异常信息,而没有具体的错误堆栈信息,如果想要排查具体异常仅通过上面的异常message内容是远远不够的

exception级别的则不但会输出错误的异常信息,还会显示具体的错误堆栈信息,使得我们在排查问题的时候有更加明确的方向

2.assert与raise的区别

​assert​​​ 的意义是在测试关键词后的条件(condition)为False时,程序自动崩溃并抛出​​AssertionError​​的异常。常用形式为:

​assert expression​​等同于以下代码:

if _debug_:
if not expression:
raise

​assert expression1, expression2​​等同于以下代码:

if _debug_:
if not expression1:
raise AssertionError(expression2)

以上两段代码中的_debug_和AssertionError都代表的是Python中内建的变量。通常在Python中_debug_在普通情况下均为True。只有在python启动时加上-o选项(生成优化后的*.pyo文件),_debug_为False。所以当程序以优化模式编译后,assert声明并不会被执行。

以下两段代码,大家可以仔细体会下他们的区别:

​assert写法​

from loguru import logger

try:

port, minimum = 10, 12

assert port >= minimum

except Exception as e:

logger.error(e)
logger.exception(e)

返回结果为:

2022-03-05 00:10:45.255 | ERROR    | __main__:<module>:11 - 
2022-03-05 00:10:45.256 | ERROR | __main__:<module>:12 -
Traceback (most recent call last):

File "/Users/lijinze/anaconda3/envs/py36/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
└ ModuleSpec(name='ipykernel_launcher', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fb5d873f828>, origin='...

*****

assert port >= minimum
│ └ 12
└ 10

AssertionError: assert port >= minimum

​raise写法​

from loguru import logger

try:

port, minimum = 10, 12

if port < minimum:

raise RuntimeError('出错了')
# raise ValueError('出错了')

except Exception as e:
logger.error(e)
logger.exception(e)

返回结果为:

2022-03-05 00:10:45.255 | ERROR    | __main__:<module>:11 - 
2022-03-05 00:10:45.256 | ERROR | __main__:<module>:12 -
Traceback (most recent call last):

File "/Users/lijinze/anaconda3/envs/py36/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
└ ModuleSpec(name='ipykernel_launcher', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fb5d873f828>, origin='...

*****

assert port >= minimum
│ └ 12
└ 10

RuntimeError: 出错了

区别:​assert​​​ 是用来确保程序的正确性,而不是用来矫正或者指示一些不可预知的错误的发生。简单来说是程序员​​debug​​​的工具,有无这段程序,不应影响程序的功能执行,但对程序正确性有影响。 ​​raise​​ 是用来检查用户输入是否正确,指示程序违反了预设的条件。

python文件的格式除了.py还有.pyc/.pyo,后两张需要经过编译再运行,其中.pyo是经过优化后编译的二进制文件,可以增加程序的稳定性,隐藏源码。而在.pyo格式的版本中是不对assert进行编译的,这也是不用assert 作为检查输入参数合法性的原因之一。

Tips:

​RuntimeError​​​,​​ValueError​​​与​​AssertionError​​都是error类

3.多线程异常处理模板

def exception_warpper(func):
functools.wraps(func)
def inner(*args, **kwargs):
func_name = ''
ret = None
try:
func_name = func.__name__
ret = func(*args, **kwargs)
except Exception as e:
logger.exception(e)
Alarm.msg('exception, {}'.format(func_name))
return ret
return inner

# 多线程业务逻辑模块
crawler_dir = os.path.join(spider_dir, 'crawler', 'crawler_*.py')
with ThreadPoolExecutor(max_workers=self.max_worker) as pool:
futures = set()
for cls_path in glob.glob(crawler_dir):
imp_cls = self._load_class(
cls_path,
'spider.crawler',
'CrawlerImpl'
)
if imp_cls is not None:
cls_obj = imp_cls()
job = pool.submit(exception_warpper(cls_obj.crawl))
futures.add(job)
else:
logger.error('spider:{} load fail!', cls_path)
for job in as_completed(futures):
result = job.result()
if result:
self.crawler_result_list.append(result)
logger.info('crawl:{}, {}', result.name, result.url)
else:
logger.warning('crawl_result is null')


举报

相关推荐

0 条评论