python打印错误堆栈 flask log python打印调用栈

admin2024-05-30  14

1. 快速打印函数的调用栈

在阅读源码的时候,有时候我们想要看整个程序的调用栈是怎样的?

比较常规的做法是使用全局搜索函数,一层一层往上走,效率非常之低。

而我习惯了使用 pdb 对代码进行调试,在使用pdb时,可以使用如下代码打出调用栈

import traceback
traceback.print_stack(file=sys.stdout)

或者直接使用 where (更简单的直接一个 w)把整个函数的调用栈给打印出来

(Pdb) where
  /usr/lib/python2.7/site-packages/eventlet/greenpool.py(82)_spawn_n_impl()
-> func(*args, **kwargs)
  /usr/lib/python2.7/site-packages/eventlet/wsgi.py(719)process_request()
-> proto.__init__(sock, address, self)
  /usr/lib64/python2.7/SocketServer.py(649)__init__()
-> self.handle()
  /usr/lib64/python2.7/BaseHTTPServer.py(340)handle()
-> self.handle_one_request()
  /usr/lib/python2.7/site-packages/eventlet/wsgi.py(384)handle_one_request()
-> self.handle_one_response()
  /usr/lib/python2.7/site-packages/eventlet/wsgi.py(481)handle_one_response()

2. 如何快速编译 Python 脚本?

pyc是一种二进制文件,是由py文件经过编译后,生成的文件,是一种byte code,py文件变成pyc文件后,加载的速度会有所提高。因此在一些场景下,可以预先编译成 pyc 文件,来提高加载速度。

编译的命令非常的简单,示例如下

$ tree demo
demo
└── main.py

$ python3 -O -m compileall demo
Listing 'demo'...
Compiling 'demo/main.py'...

$ tree demo
demo
├── __pycache__
│   └── main.cpython-39.opt-1.pyc
└── main.py

3. 交互模式下下划线的秒用

对于 _ ,大家对于他的印象都是用于占位符,省得为一个不需要用到的变量,绞尽脑汁的想变量名。

今天要介绍的是他的第二种用法,就是在交互式模式下的应用。

示例如下:

>>> 3 + 4
7
>>> _
7
>>> name='iswbm'
>>> name
'iswbm'
>>> _
'iswbm'

它记录的是上一次表达式中返回的 非 None 值

一定要是非 None值 ,否则 _ 存储的值不会被更新。这就是为什么print函数打印出来的值不会被存储。

>>> 3 + 4
7
>>> _
7
>>> print("iswbm")
iswbm
>>> _
7

因为 print 函数打印的内容并不是函数本身的返回值,print 函数返回的 None

4. 让脚本报错后立即进入调试模式

当你在使用 python xxx.py 这样的方法,执行 Python 脚本时,若因为代码 bug 导致异常未捕获,那整个程序便会终止退出。

这个时候,我们通常会去排查是什么原因导致的程序崩溃。

大家都知道,排查问题的思路,第一步肯定是去查看日志,若这个 bug 隐藏的比较深,只有在特定场景下才会现身,那么还需要开发者,复现这个 bug,方能优化代码。

复现有时候很难,有时候虽然简单,但是要伪造各种数据,相当麻烦。

如果有一种方法能在程序崩溃后,立马进入调试模式该有多好啊?

既然都这么问了,那肯定是带着解决方案来的。

只要你在执行脚本行,加上 -i 参数,即可在脚本执行完毕后进入 Python Shell 模式,方便你进行调试。

具体演示如下:

python打印错误堆栈 flask log python打印调用栈,python打印错误堆栈 flask log python打印调用栈_linux,第1张

需要注意的是:脚本执行完毕,有两种情况:

  1. 正常退出
  2. 异常退出

这两种都会进入 Python Shell,如果脚本并无异常,最终也会进入 Python Shell 模式,需要你手动退出

python打印错误堆栈 flask log python打印调用栈,python打印错误堆栈 flask log python打印调用栈_linux_02,第2张

如果希望脚本正确完成时自动推出,可以在脚本最后加上一行__import__("os")._exit(0)

5. 快速将项目打包成应用程序

假设我当前有一个 demo 项目,目录结构树及相关文件的的代码如下

python打印错误堆栈 flask log python打印调用栈,python打印错误堆栈 flask log python打印调用栈_学习_03,第3张

现在我使用如下命令,将该项目进行打包,其中 demo 是项目的文件夹名,main:main 中的第一个 main 指的 main.py,而第二个 main 指的是 main 函数

$ python3 -m zipapp demo -m "main:main"

执行完成后,会生成一个 demo.pyz 文件,可直接执行它。

具体演示过程如下

python打印错误堆栈 flask log python打印调用栈,python打印错误堆栈 flask log python打印调用栈_开发语言_04,第4张

6. 往 Python Shell 中传入参数

往一个 Python 脚本传入参数,是一件非常简单的事情。

比如这样:

$ python demo.py arg1 arg2

我在验证一些简单的 Python 代码时,喜欢使用 Python Shell 。

那有没有办法在使用 Python Shell 时,向上面传递参数一样,传入参数呢?

经过我的摸索,终于找到了方法,具体方法如下:

python打印错误堆栈 flask log python打印调用栈,python打印错误堆栈 flask log python打印调用栈_Python_05,第5张

7. 最快查看包搜索路径的方式

当你使用 import 导入一个包或模块时,Python 会去一些目录下查找,而这些目录是有优先级顺序的,正常人会使用 sys.path 查看。

>>> import sys
>>> from pprint import pprint   
>>> pprint(sys.path)
['',
 '/usr/local/Python3.7/lib/python37.zip',
 '/usr/local/Python3.7/lib/python3.7',
 '/usr/local/Python3.7/lib/python3.7/lib-dynload',
 '/home/wangbm/.local/lib/python3.7/site-packages',
 '/usr/local/Python3.7/lib/python3.7/site-packages']
>>>

那有没有更快的方式呢?

我这有一种连 console 模式都不用进入的方法呢?

你可能会想到这种,但这本质上与上面并无区别

[wangbm@localhost ~]$ python -c "print('\n'.join(__import__('sys').path))"

/usr/lib/python2.7/site-packages/pip-18.1-py2.7.egg
/usr/lib/python2.7/site-packages/redis-3.0.1-py2.7.egg
/usr/lib64/python27.zip
/usr/lib64/python2.7
/usr/lib64/python2.7/plat-linux2
/usr/lib64/python2.7/lib-tk
/usr/lib64/python2.7/lib-old
/usr/lib64/python2.7/lib-dynload
/home/wangbm/.local/lib/python2.7/site-packages
/usr/lib64/python2.7/site-packages
/usr/lib64/python2.7/site-packages/gtk-2.0
/usr/lib/python2.7/site-packages

这里我要介绍的是比上面两种都方便的多的方法,一行命令即可解决

[wangbm@localhost ~]$ python3 -m site
sys.path = [
    '/home/wangbm',
    '/usr/local/Python3.7/lib/python37.zip',
    '/usr/local/Python3.7/lib/python3.7',
    '/usr/local/Python3.7/lib/python3.7/lib-dynload',
    '/home/wangbm/.local/lib/python3.7/site-packages',
    '/usr/local/Python3.7/lib/python3.7/site-packages',
]
USER_BASE: '/home/wangbm/.local' (exists)
USER_SITE: '/home/wangbm/.local/lib/python3.7/site-packages' (exists)
ENABLE_USER_SITE: True

从输出你可以发现,这个列的路径会比 sys.path 更全,它包含了用户环境的目录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!