python运行程序为什么会卡住_为什么我的 Python 程序卡住啦!

本文简答介绍在linux环境下如何利用gdb来分析卡住的程序,本文使用的Python为Cpython2.7,操作系统为Debian。

阻塞在IO

程序被卡住,很可能是程序被阻塞了,即在等待(wait)等个系统调用的结束,比如磁盘IO与网络IO、多线程,默认的情况下很多系统调用都是阻塞的。多线程的问题复杂一下,后面专门介绍。下面举一个UDP Socket的例子(run_forever_block.py):

# -*- coding: utf-8 -*-

import socket

def simple_server:

address = ('0.0.0.0', 40000)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

s.bind(address)

while True:

data, addr = s.recvfrom(2048)

if not data:

print "client has exist"

break

print "received:", data, "from", addr

if __name__ == '__main__':

simple_server

这是一个简单的UDP程序,代码在(0.0.0.0, 40000)这个地址上等待接收数据,核心就是第10行的recvfrom函数,这就是一个阻塞(blocking)的系统调用,只有当读到数据之后才会返回,因此程序会卡在第10行。当然,也可以通过fcntl设置该函数为非阻塞(non-blocking)。

我们来看看阻塞的情况,运行程序,然后通过top查看这个进程的状态

可以看到这个进程的pid是26466,进程状态为S(Sleep),CPU为0.0。进程状态和CPU都暗示我们,当前进程正阻塞在某个系统调用。这个时候,有一个很好使的命令:strace,可以跟踪进程的所有系统调用,我们来看看

> ~$ strace -T -tt -e trace=all -p 26466

> Process 26466 attached

> 19:21:34.746019 recvfrom(3,

可以看到,进程卡在了recvfrom这个系统调用,对应的文件描述符(file deor)是3,其实通过recvfrom这个名字,大致也能定位问题。关于文件描述符,还有一个更实用的命令,lsof(list open file),可以看到当前进程打开的所有文件,在linux下,一切皆文件,自然也就包括了socket。

> lsof -p 26466

> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

>

> ...

> python 26466 xxxxxxx **3u** IPv4 221871586 0t0 UDP *:40000

从上面可以看出这个文件描述符(3U)更详细的信息,比如是IPV4 UDP,监听在40000端口等等。

使用gdb调试Python程序

上面这个例子非常的

你可能感兴趣的:(python运行程序为什么会卡住_为什么我的 Python 程序卡住啦!)