在将输出写入文件时使用多处理显示来自子进程的实时输出

Posted

技术标签:

【中文标题】在将输出写入文件时使用多处理显示来自子进程的实时输出【英文标题】:Using multiproccessing for displaying realtime output from Subproccess while writing the output to file 【发布时间】:2020-09-20 08:49:04 【问题描述】:

我有一个获取主机地址的代码,询问文件名(保存在用户的桌面上)并询问用户是否要清除文件或附加到它。

当它运行时,它首先将输出打印到屏幕上,然后再写入文件。 如何使用多进程使它们同时工作? 我已经尝试使用 target= 并且它们运行但仍然一个接一个而不是一起运行。

.................................................. ..................................................... ....................................

(不要介意主机、文件名、清除输入验证,它们是为了测试多进程)

代码:(我用第一个条件来测试多进程)

import multiprocessing as mp
import subprocess as sub
import sys
import os

class pingURL():

    def __init__(self):
        self.t2d = mp.Queue()
        self.tf = mp.Queue()
        host = input("Enter Host: ")
        filename = input("Enter filename: ")
        clear = input("Clear File? [Y/n] ")

        print(clear, filename)  # For Debugging Input Validation

        if clear.lower() == 'y' and filename == '':
            self.pHclrFileYesFnNo(host)
            # self.clrFileYesFnNoWritefile(host)
            # self.clrFileYesFnNoPrintoutput(host)
        elif clear.lower() == 'n' and filename == '':
            self.clrFileNoFnNoPrintoutput(host)
            self.clrFileNoFnNoWritefile(host)
        elif clear.lower() == 'y' and filename != '':
            self.clrFileYesFnYesPrintoutput(host)
            self.clrFileYesFnYesWritefile(host, filename)
        elif clear.lower() == 'n' and filename != '':
            self.clrFileNoFnYesPrintoutput(host)
            self.clrFileNoFnYesWritefile(host, filename)

    def pHclrFileYesFnNo(self, host):

        procs = []

        proc = mp.Process(name="Clear + No Filename + Print Output", target=self.clrFileYesFnNoPrintoutput(host))
        proc2 = mp.Process(name="Clear + No Filename + Write to file", target=self.clrFileYesFnNoWritefile(host))

        procs.append(proc)
        procs.append(proc2)

        for proc in procs:
            proc.start()
            proc.join()


    def clrFileYesFnNoPrintoutput(self, host):

        print(f'Number of procceccess: mp.cpu_count()')
        print(f'Current Proccess: mp.current_process().name + mp.current_process().pid')

        with sub.Popen(['ping', f'host'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    def clrFileYesFnNoWritefile(self, host):

        print(f'Number of procceccess: mp.cpu_count()')
        print(f'Current Proccess: mp.current_process().name + mp.current_process().pid')

        file = fr'c:/users/os.getlogin()/Desktop/default.txt'
        with open(file, 'a') as output:
            output.truncate(0)
            sub.call(['ping', f'host'], stdout=output)

        output.close()

    def clrFileNoFnNoPrintoutput(self, host):

        with sub.Popen(['ping', f'host'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    def clrFileNoFnNoWritefile(self, host):

        file = fr'c:/users/os.getlogin()/Desktop/default.txt'
        with open(file, 'a') as output:
            sub.call(['ping', f'host'], stdout=output)

        output.close()

    def clrFileYesFnYesPrintoutput(self, host):

        with sub.Popen(['ping', f'host'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    def clrFileYesFnYesWritefile(self, host, filename):

        file = fr'c:/users/os.getlogin()/Desktop/filename.txt'
        with open(file, 'a') as output:
            output.truncate(0)
            sub.call(['ping', f'host'], stdout=output)

        output.close()

    def clrFileNoFnYesPrintoutput(self, host):

        with sub.Popen(['ping', f'host'], stdout=sub.PIPE,
                       bufsize=1, universal_newlines=True, stderr=sub.STDOUT) as p:
            for line in p.stdout:
                print(line, end=' ')

    def clrFileNoFnYesWritefile(self, host, filename):

        file = fr'c:/users/os.getlogin()/Desktop/filename.txt'
        with open(file, 'a') as output:
            sub.call(['ping', f'host'], stdout=output)

        output.close()


if __name__ == "__main__":

    pingURL()

我在运行脚本时得到相同的进程名称和 ID:

【问题讨论】:

【参考方案1】:

解决方案是为每个条件定义一个处理程序。 这对我有用。

def pHclrFileNoFnNo(self, host):

    procs = []
    proc = mp.Process(target=self.clrFileNoFnNoWritefile, args=(host,))
    proc.daemon = False
    proc2 = mp.Process(target=self.clrFileNoFnNoPrintoutput, args=(host,))
    proc2.daemon = True

    procs.append(proc)
    procs.append(proc2)

    for proc in procs:
        proc.start()

【讨论】:

以上是关于在将输出写入文件时使用多处理显示来自子进程的实时输出的主要内容,如果未能解决你的问题,请参考以下文章

在文件中写入打印日志时,Python子进程在屏幕缓冲区中延迟

Python子进程显示在终端上登录并保存在文件中

Python:如何写入子进程的标准输入并实时读取其输出

golang如何获取子进程的实时输出

Python多处理安全地写入文件

子进程写入文件时经常检查文件