python--杂识--9.3--subprocess.Popen 非阻塞读

1 python2

#! -*- coding: utf-8 -*-
import os
import fcntl
import subprocess
import time


def non_block_read(output):
    fd = output.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)


def test():
    cmdline = "ping 127.0.0.1 -w 5"
    cmdlist = cmdline.split()
    p = subprocess.Popen(cmdlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    non_block_read(p.stdout)  # 避免stdout中没有结果时读会阻塞,此种方法可能会丢失一些结果信息
    resinfo = ""
    while True:
        try:
            resinfo = p.stdout.readline()  # 1 读时不会阻塞; 2 当stdout中没有结果时会出现异常; 3 当所有结果已取完后再次取的时候会取到空字符串。
        except Exception as e:
            resinfo = None
        if resinfo:
            print(resinfo)
        if resinfo is not None and resinfo == "":
            break
        

if __name__ == "__main__":
    test()


"""
运行结果:
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.015 ms

64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.026 ms

64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.026 ms

64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.026 ms

64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.024 ms



--- 127.0.0.1 ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 4002ms

rtt min/avg/max/mdev = 0.015/0.023/0.026/0.006 ms
"""

2 python3

import os
import fcntl
import subprocess
import time


def non_block_read(output):
    fd = output.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)


def test():
    cmdline = "ping 127.0.0.1 -w 5"
    cmdlist = cmdline.split()
    p = subprocess.Popen(cmdlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    non_block_read(p.stdout)  # 避免stdout中没有结果时读会阻塞,此种方法可能会丢失一些结果信息
    resinfo = ""
    while True:
        resinfo = p.stdout.readline().decode("utf-8")  # 1 读时不会阻塞; 2 当stdout中没有结果时取到空字符串,注意与python2的不同。

        if resinfo:
            print(resinfo)
        completed = p.poll()  # 命令执行完成时poll()会返回一个数字,0表示执行成功,非0表示执行失败;命令正在执行过程中poll()会返回None
        if completed is not None:
            resinfo = p.stdout.readline().decode("utf-8")  # 虽然命令已执行完但stdout中的结果可能还没取完
            if not resinfo:
                break
            print(resinfo)
        time.sleep(0.5)


if __name__ == "__main__":
    test()


"""
运行结果:
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.014 ms

64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.022 ms

64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.016 ms

64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.024 ms

64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.022 ms

64 bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.025 ms



--- 127.0.0.1 ping statistics ---

6 packets transmitted, 6 received, 0% packet loss, time 4999ms

rtt min/avg/max/mdev = 0.014/0.020/0.025/0.006 ms
"""

3 python3

建议使用以下异步的方式

import threading
import subprocess
import time


def test():
    cmdline = "ping 127.0.0.1 -w 5"
    cmdlist = cmdline.split()
    p = subprocess.Popen(cmdlist, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
    while True:
        resinfo = p.stdout.readline()  # 1 读时不会阻塞; 2 当stdout中没有结果时取到空字符串,注意与python2的不同。

        if resinfo:
            print(resinfo)
        completed = p.poll()  # 命令执行完成时poll()会返回一个数字,0表示执行成功,非0表示执行失败;命令正在执行过程中poll()会返回None
        if completed is not None:
            resinfo = p.stdout.readline()  # 虽然命令已执行完但stdout中的结果可能还没取完
            if not resinfo:
                break
            print(resinfo)
        time.sleep(0.5)


if __name__ == "__main__":
    thr = threading.Thread(target=test)
    thr.setDaemon(True)
    thr.start()
    thr.join()  # 在业务代码中这行需要注掉,不能阻塞主线程往下执行
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值