【问题标题】:Python, running a subprocess and read output and not hanging the programPython,运行子进程并读取输出而不挂起程序
【发布时间】:2013-07-02 23:55:34
【问题描述】:

在这里的第一篇文章,我必须说我对一般的编程有点业余...... 我在 osx 上使用 python 2.7.5 子进程模块来读取名为 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 模块,但我并不真正了解它们是如何工作的……我想我必须启动一个运行该实用程序的线程和另一个线程来监听它?

【问题讨论】:

    标签: python python-2.7 subprocess python-multithreading dns-sd


    【解决方案1】:

    这是一个作为新进程运行的类的非常基本的实现。这将允许你在你的主脚本/进程中继续执行但是如果你想做任何事情,你将需要使用某种进程间通信(即共享内存数据结构described in multiprocessing docs)父进程中子进程的输出。

    from sys import *
    from subprocess import *
    import multiprocessing
    
    class ProcessNAS(multiprocessing.Process):
        def __init__ (self, name):
            self.name_ = name
            self.status = False
            self.process = None
            super(ProcessNAS, self).__init__(target=self.StartCheck)
    
        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.start()  # <-- instead of StartCheck(), call start()
    
    import time
    time.sleep(4)
    newCheckNAS.terminate()  # <-- now have two processes - able to kill the child
    

    【讨论】:

    • 这很酷,谢谢。整件事有效,但只有一件事。在“导入时间”,我通过使用 Sleep(1) 并打印 ewCheckNAS.status 开始一个 300 秒的循环。但是,看起来类“self.status”属性没有更新......
    • @ChristianSirois 正确。不会,因为您已经分叉了一个新进程并且没有设置任何共享内存。您需要使用 multiprocesing.value 之类的东西才能访问不断变化的变量。另一个非常简单的解决方案是写入临时文件并从主进程中读取。
    • 我决定将所有内容输出到一个文件中,以便在我方便时读取。这个解决方案很完美:) 非常感谢。
    猜你喜欢
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多