NoOps

Ops make no ops | Ops的目标是没有Ops,嗯!

小心subprocess的PIPE卡住你的python程序

作者: |   5,956 浏览  | 

python 2.4后引入新的模块subprocess,用于取代原有的commands模块。利用subprocess可以非常方便地跑多个后台任务,例如下面的示例代码(省去所有的错误处理):

有了subprocess之后,生活变得更加美好了,但是,上面的代码一不小心就会让你掉入难以追查的坑中,subprocess调用的子进程可能hang住,而poll会永远无法等到子进程结束。Complete deadlock!

经过多次试错后发现,cmd命令输出(标准或者错误)小于65536字节时,程序运行完全正常,当输出大于等于65536后,程序立马hang住,看来问题就可能出在输出过多数据上。

查看python的源码发现,如果设置了stdout或stderr,subprocess就会调用os.pipe创建一个管道用于其和子进程之间的通信,而上面的问题正好是cmd输出的数据把pipe塞满,无法继续往pipe里写入数据导致程序hang住,而我们没有去读出pipe数据,而是死等子进程完成,导致死锁。

解决上面的问题可以有两种简单的方法:

1、使用文件代替PIPE,解除PIPE大小的限制:

2、使用communicate及时读出pipe中内容,避免堵死,但在输出量非常大的情况下会影响性能:

 

2 Comments

  1. xiao.li
    2013/05/10 at 12:51 上午

    森哥写的不错哦

  2. yunqi
    2013/10/02 at 1:35 上午

    In the second solution, p[0].communicate() itself is a blocking process, so it will wait until each process terminates and would not perform as you expected.

发表评论