在 Python 中运行子进程并读取输出而不会挂起程序

我们正在使用 Python 2.7.5 的 subprocess 模块在 macOS 系统中读取一个名为 dns-sd 的实用程序的输出。我们的目标是找出网络上正在运行的 SSH 文件服务器。使用 “dns-sd -B _ssh._tcp .” 可以正常工作,如下代码所示:
在这里插入图片描述

from sys import *
from subprocess import *

class ProcessNAS(object):
    def __init__ (self, name):
        self.name = name
        self.status = False
        self.process = None

    def StartCheck(self):
        print "Checking for NAS..."
        stdout.flush()
        self.process = Popen( ["dns-sd", "-B", "_ssh._tcp", "."], stdout=PIPE )

        while True:
            line = self.process.stdout.readline()[:-1]
            print line
            if "Add" in line and self.name in line:
                self.status = True
                print "NAS '" + self.name + "' is available."
            elif "Rmv" in line and self.name in line:
                self.status = False
                print "NAS '" + self.name + "' is unavailable."


newCheckNAS = ProcessNAS("Drobo-FS")
newCheckNAS.StartCheck()

这是一个“实时”实用程序,如果 Python 脚本持续运行,dns-sd 输出的新行将自动显示在打印中。这是一个典型的输出:

Checking for NAS...
Browsing for _ssh._tcp
DATE: ---Tue 02 Jul 2013---
19:44:30.670  ...STARTING...
Timestamp     A/R Flags if Domain       Service Type       Instance Name
19:48:07.061  Add     2  4 local.       _ssh._tcp.         Drobo-FS
NAS 'Drobo-FS' is available.

问题在于,一旦我们调用 newCheckNAS.StartCheck(),程序的其余部分会一直等待 dns-sd 实用程序完成才继续运行。但是这个实时实用程序永远不会停止,它需要在后台继续监视。我们研究了各种线程、多处理甚至 pybonjour 模块,但我们不真正理解它们是如何工作的。我们猜测我们必须启动一个线程来运行这个实用程序,再启动另一个线程来监听它?

2、解决方案

要解决这个问题,我们需要使用线程来运行 dns-sd 实用程序,这样我们就不会阻塞主程序。以下是修改后的代码:

from sys import *
from subprocess import *

class ProcessNAS(object):
    def __init__ (self, name):
        self.name = name
        self.status = False
        self.process = None

    def StartCheck(self):
        print "Checking for NAS..."
        stdout.flush()

        def read_output(process):
            while True:
                line = process.stdout.readline()[:-1]
                if not line:
                    break
                print line
                if "Add" in line and self.name in line:
                    self.status = True
                    print "NAS '" + self.name + "' is available."
                elif "Rmv" in line and self.name in line:
                    self.status = False
                    print "NAS '" + self.name + "' is unavailable."

        self.process = Popen( ["dns-sd", "-B", "_ssh._tcp", "."], stdout=PIPE )
        self.thread = Thread(target=read_output, args=(self.process,))
        self.thread.start()

newCheckNAS = ProcessNAS("Drobo-FS")
newCheckNAS.StartCheck()

这个代码会创建一个 ProcessNAS 对象,它表示我们要监视的 SSH 文件服务器。StartCheck 方法启动 dns-sd 实用程序并创建一个新的线程来读取它的输出。read_output 方法从 dns-sd 实用程序读取输出并将其打印到控制台。

现在,当我们调用 newCheckNAS.StartCheck() 时,主程序不会被阻塞,并且我们可以继续执行其他任务,同时 dns-sd 实用程序在后台运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值