部分阅读" stdout"在Python上使用Popen

时间:2014-10-06 07:42:45

标签: python bash stdout popen

我正在尝试构建一个python脚本,它打开一个子进程(bash脚本)并在10秒内将“stdout”读入变量。 10秒后,我需要通过POST请求将数据传输到服务器。 我知道如何发出POST请求,但如何在10秒内收集“stdout”?

我找到了很多例子如何使用“Popen”,启动bash脚本并立即读取stderr而没有biffering,但如何在一段时间内收集输出并释放部分?

3 个答案:

答案 0 :(得分:0)

你可以做类似下面的事情:

  1. 将子流程指向输出到控制台输出
  2. 捕获一个变量,该变量对于发布和捕获函数来说是常见的
  3. 设置线程每10秒发布一次日志
  4. 导入线程,sys,subprocess

    out = ""
    def postLogs():
        print out
        #do your posting here
        threading.Timer(10.0, postLogs).start() #execute this function every 10 seconds
    
    proc = subprocess.Popen("ping google.com", shell=True,stdout=subprocess.PIPE,     stderr=subprocess.STDOUT)
    while proc.poll() is None:
        out = proc.stdout.readline()
        sys.stdout.flush
        if out != "":
            postLogs()
    

答案 1 :(得分:0)

我认为这个带有两个简单职责的线程的解决方案是干净而优雅的。

import os
import subprocess
import threading
import functools

from time import sleep

class OutputMonitor(threading.Thread):

    """ Start the subprocess in separate thread and append it's output to a buffer. """

    def __init__(self, cmd):
        super(OutputMonitor, self).__init__()
        self.daemon = True
        self.cmd = cmd
        self.buffer = ''
        self.buflock = threading.Lock()

    def run(self):

        popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        while popen.poll() is None:
            data = popen.stdout.read(4)
            if data != "":
                with self.buflock:
                    self.buffer += data

    def get_current_output(self):
        with self.buflock:
            buf = self.buffer
            self.buffer = ""
            return buf

class OutputHandler(threading.Thread):

    """
        Start a thread responsible for tracking subprocess output, and periodically
        check if it has produced new output. If so, call handler to process this data.
    """

    def __init__(self, cmd, interval, filepath):
        super(OutputHandler, self).__init__()
        self.om = OutputMonitor(cmd)
        self.interval = interval

        # Replace it with your handler init...
        self.filepath = filepath
        if os.path.exists(self.filepath):
            os.unlink(self.filepath)

    def run(self):

        self.om.start()
        while self.om.is_alive():
            sleep(self.interval)
            data = self.om.get_current_output()

            self._handle_data_chunk(data)

    def _handle_data_chunk(self, data):

        # Replace it with you handling.
        with open(self.filepath, 'a') as f:
            f.write(data)


if __name__ == '__main__':

    logfile_path = "C:\\log.txt"

    interval = 5
    cmd = ['ping', 'n', '10', '127.0.0.1']

    oh = OutputHandler(cmd, interval, logfile_path)
    oh.start()
    oh.join()

答案 2 :(得分:0)

好的,继续使用 mrad 脚本 我编辑它只是一点点。添加了对文件功能的写入,它完美无缺。与

ping google.com

但它无法使用我需要的命令...我需要启动ffmpeg。我需要的命令是

ffmpeg -i "my rtsp link" -vcodec copy -loglevel verbose -an -f flv "my RTMP link"

当我将命令放在此代码中时 - 我立即看到输出。 2-没有保存在文件中(

import subprocess
import threading
from datetime import datetime
from time import sleep   
from Queue import Queue

class Monitor(threading.Thread):

    def __init__(self, queue, cmd):
        super(Monitor, self).__init__()
        self.queue = queue
        self.cmd = cmd

    def run(self):
        popen = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, shell=True)
        while popen.poll() is None:
            line = popen.stdout.readline()
            self.queue.put(line)       

def foo(cmd, interval):

    q = Queue()
    m = Monitor(q, cmd)
    m.start()

    while m.is_alive():
        sleep(interval)
        current_queue_length = q.qsize()
        chunk = ''
        for i in xrange(current_queue_length):
            chunk += q.get()
    print chunk 
    f=open("/home/pi/raf/log.txt","a")  #trying to write to log 
    f.write(chunk)      
    f.close()


if __name__ == '__main__':
    cmd = 'ping google.com'
    interval = 3
    foo(cmd, interval)