免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 15766 | 回复: 10
打印 上一主题 下一主题

为什么subprocess.Popen.poll()=0,但是pipe里面还有没读完的数据 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-10-18 14:58 |只看该作者 |倒序浏览
可能标题写的有点不清楚,具体情况如下:
写一个程序,能获得程序输出,并且在程序执行完毕之后,能获知。程序如下
  1. import subprocess

  2. pp = subprocess.Popen('ping -c4 www.google.cn', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  3. while 1:
  4.         line = pp.stdout.readline()
  5.         print('out-->'+line+'<')
  6.         if subprocess.Popen.poll(pp)==0:
  7.                 break

  8. print('DONE')
复制代码
实际执行的效果有2种情况
第一种
out-->PING www.google.cn (203.208.45.212) 56(84) bytes of data.<
out-->64 bytes from 203.208.45.212: icmp_seq=1 ttl=55 time=4.03 ms<
out-->64 bytes from 203.208.45.212: icmp_seq=2 ttl=55 time=3.18 ms<
out-->64 bytes from 203.208.45.212: icmp_seq=3 ttl=55 time=3.90 ms<
out-->64 bytes from 203.208.45.212: icmp_seq=4 ttl=55 time=4.47 ms<
DONE

---------------------------
第二种

out-->PING www.google.cn (203.208.46.212) 56(84) bytes of data.<
out-->64 bytes from 203.208.46.212: icmp_seq=1 ttl=54 time=26.3 ms<
out-->64 bytes from 203.208.46.212: icmp_seq=2 ttl=54 time=3.22 ms<
out-->64 bytes from 203.208.46.212: icmp_seq=3 ttl=54 time=6.95 ms<
out-->64 bytes from 203.208.46.212: icmp_seq=4 ttl=54 time=4.59 ms<
out--><
out-->--- www.google.cn ping statistics ---<
out-->4 packets transmitted, 4 received, 0% packet loss, time 3009ms<
out-->rtt min/avg/max/mdev = 3.225/10.282/26.363/9.380 ms<
out--><
out--><
out--><
out--><
DONE

第一种执行结果占多数,第二种执行结果,有时候会出现。

按照实际执行ping -c4 www.google.cn的情况看,第一种情况少了最后的三行,所以说是不正确的。但是为什么常常是这种情况哪?求版主和各位大大帮忙看看那问题。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
2 [报告]
发表于 2012-10-18 15:23 |只看该作者
poll就别用了, 有延迟, 直接根据readline返回EOF做判定, 最后记得wait回收子进程, 否则有僵尸.
  1. [root@vps616 python]# python main.py
  2. out-->PING www.google.cn (203.208.46.212) 56(84) bytes of data.<
  3. out-->64 bytes from 203.208.46.212: icmp_seq=1 ttl=54 time=2.41 ms<
  4. out-->64 bytes from 203.208.46.212: icmp_seq=2 ttl=54 time=2.06 ms<
  5. out-->64 bytes from 203.208.46.212: icmp_seq=3 ttl=54 time=2.14 ms<
  6. out-->64 bytes from 203.208.46.212: icmp_seq=4 ttl=54 time=2.65 ms<
  7. out--><
  8. out-->--- www.google.cn ping statistics ---<
  9. out-->4 packets transmitted, 4 received, 0% packet loss, time 3007ms<
  10. out-->rtt min/avg/max/mdev = 2.064/2.318/2.658/0.237 ms<
  11. DONE
  12. [root@vps616 python]# cat main.py
  13. #python2.7.3
  14. #coding=utf-8

  15. import subprocess

  16. pp = subprocess.Popen('ping -c4 www.google.cn', shell = True, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)

  17. while True:
  18.     line = pp.stdout.readline()
  19.     if not line:
  20.                 break
  21.     print('out-->' + line.strip() + '<')

  22. pp.wait()
  23. print('DONE')
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-10-18 15:30 |只看该作者
回复 1# spyman1802

if subprocess.Popen.poll(pp) !=None:
  break

poll的返回: A None value indicates that the process hasn’t terminated yet.A negative value -N indicates that the child was terminated by signal N (Unix only).


   

论坛徽章:
0
4 [报告]
发表于 2012-10-18 15:36 |只看该作者
回复 2# linux_c_py_php

多谢。 顺带也拜访了一下个人主页,做的非常好,可以直接去百度。?? 为什么不是google??

我想问一下延迟是什么意思?
   

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
5 [报告]
发表于 2012-10-18 16:00 |只看该作者
可能是进程退出前关闭描述符距离进程完全结束有一定的时间间隔, 导致Poll的实现(kill -0 child_pid, 猜测 )和readline返回EOF之间有差距, 所以导致多打印了很多空行, 也就是readline()一直读EOF, 而poll依旧检测到子进程存在.

spyman1802 发表于 2012-10-18 15:36
回复 2# linux_c_py_php

多谢。 顺带也拜访了一下个人主页,做的非常好,可以直接去百度。?? 为什么不 ...

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
6 [报告]
发表于 2012-10-18 16:00 |只看该作者
汗, 站点没放出来, 推倒好几版了, 找不到太好的主题.

spyman1802 发表于 2012-10-18 15:36
回复 2# linux_c_py_php

多谢。 顺带也拜访了一下个人主页,做的非常好,可以直接去百度。?? 为什么不 ...

论坛徽章:
0
7 [报告]
发表于 2012-10-18 16:12 |只看该作者
回复 3# 106033177


   
谢谢回复。 我看过这段官方回应,不过实际执行效果确实不好,我发按照你的描述改过的代码,你可以自己在linux上面执行试试看。
  1. import subprocess

  2. pp = subprocess.Popen('ping -c4 www.google.cn', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  3. while 1:
  4.         line = pp.stdout.readline()
  5.         print('out-->'+line.strip()+'<')
  6.         if subprocess.Popen.poll(pp) is not None:
  7.                 break

  8. print('DONE')
复制代码

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
8 [报告]
发表于 2012-10-18 16:48 |只看该作者
spyman1802 发表于 2012-10-18 16:12
回复 3# 106033177


是一样的, 我之前已经试过了, 多打印很多空行, 原因应该是我分析的那样, 所以你不要用pull了.

论坛徽章:
0
9 [报告]
发表于 2012-10-19 14:48 |只看该作者
回复 1# spyman1802
回复 2# linux_c_py_php
spyman1802 发表于 2012-10-18 14:58
out-->64 bytes from 203.208.46.212: icmp_seq=3 ttl=54 time=6.95 ms<
out-->64 bytes from 203.208.46.212: icmp_seq=4 ttl=54 time=4.59 ms<
out--><
out-->--- www.google.cn ping statistics ---<
out-->4 packets transmitted, 4 received, 0% packet loss, time 3009ms<

这个应该是缓冲导致的,实际上第一种输出是不完整的。
子进程退出了并不表示管道里没有数据了,所以
if subprocess.Popen.poll(pp)==0:
  break
这样判断会有部分数据没有读取就退出循环了。


   

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
10 [报告]
发表于 2012-10-19 19:47 |只看该作者
这个分析是对的, 没想到读管道这一点.

106033177 发表于 2012-10-19 14:48
回复 1# spyman1802
回复 2# linux_c_py_php
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP