【问题标题】:Lock process until subprocess reaches a certain point锁定进程直到子进程到达某个点
【发布时间】:2015-03-10 13:58:42
【问题描述】:

我正在并行运行多个子进程,但我需要锁定每个进程,直到子进程给出输出(通过打印功能)。子进程正在运行已打包为可执行文件的 python 脚本。

代码如下:

import multiprocessing as mp
import subprocess
import os


def main(args):

    l,inpath = args
    l.acquire()
    print "Running KNN.exe for files in %s" %   os.path.normpath(inpath).split('\\')[-1] 

    #Run KNN executable as a subprocess
    subprocess.call(os.path.join(os.getcwd(), "KNN.exe"))
    #This is where I want to wait for any output from the subprocess before releasing the lock
    l.release()

    #Here I would like to wait until subprocess is done then print that it is done
    l.acquire()
    print "Done %s" % os.path.normpath(inpath).split('\\')[-1]
    l.release()


if __name__ == "__main__":
    #Set working directory path containing input text file
    os.chdir("C:\Users\Patrick\Google Drive\KNN")
    #Get folder names in directory containing GCM input
    manager = mp.Manager()
    l = manager.Lock()
    gcm_dir = "F:\FIDS_GCM_Data_CMIP5\UTRB\UTRB KNN-CAD\Input"
    paths = [(l, os.path.join(gcm_dir, folder)) for folder in os.listdir(gcm_dir)]    
    #Set up multiprocessing pool
    p = mp.Pool(mp.cpu_count())
    #Map function through input paths
    p.map(main, paths)

所以目标是锁定进程,以便子进程可以运行,直到收到输出。之后可以释放锁并且子进程可以继续,直到它完成,然后我想打印它已经完成。

我的问题是如何在释放进程上的锁(多个)之前等待子进程的单个(并且唯一)输出?

另外,我怎样才能等待进程终止然后打印它已完成?

【问题讨论】:

    标签: python locking multiprocessing subprocess


    【解决方案1】:

    您的代码使用了call 方法,该方法已经在等待子进程完成(这意味着所有输出都已生成)。我从您的问题推断出您希望能够区分何时首次写入输出和何时完成子流程。以下是我推荐的内联修改代码:

    def main(args):
    
        l,inpath = args
        l.acquire()
        print "Running KNN.exe for files in %s" %   os.path.normpath(inpath).split('\\')[-1]
    
        #Run KNN executable as a subprocess
        #Use the Popen constructor
        proc = subprocess.Popen(os.path.join(os.getcwd(), "KNN.exe"), stdout=subprocess.PIPE)
    
        #This is where I want to wait for any output from the subprocess before releasing the lock
        # Wait until the subprocess has written at least 1 byte to STDOUT (modify if you need different logic)
        proc.stdout.read(1)
    
        l.release()
    
        #Here I would like to wait until subprocess is done then print that it is done
        #proc.wait()
        (proc_output, proc_error) = proc.communicate()
    
        l.acquire()
        print "Done %s" % os.path.normpath(inpath).split('\\')[-1]
        l.release()
    

    请注意,上述内容并不假设您想对子进程的输出做任何事情,除了检查它是否已生成。如果您想对该输出做任何不那么琐碎的事情(消耗 1 个字节,然后将其放在地板上),proc.stdout(这是一个file 对象)应该代表子进程在运行时生成的所有内容.

    【讨论】:

    • 啊,太好了!是的,区分子进程的第一个输出和它的终止正是我的意思。在这种情况下我只需要第一个输出,但我认为proc.stdout 将来会有用。
    • @user2593236 如果有帮助,我很高兴。只是为了再次强调我的回答中的警告,如果proc.stdout.read(1) 的结果没有被分配给任何东西,那么第一个字节将被丢弃。所以这很好,只要“需要第一个输出”意味着你不是说“需要知道第一个输出字节是什么”。 :)
    • @pbreach:如果子进程产生足够的输出,答案中写的代码可能会死锁(至少在 Unix 上,我不知道管道缓冲区是否可以在 Windows 上无限增长)。您应该读取输出,例如,deque(p.stdout, maxlen=0); p.stdout.close(); p.wait() 以在读取第一个字节后丢弃它,或 out, err = p.communicate() 以字符串形式捕获输出。
    • @JFSebastian Well-spotted...answer 已被编辑为使用 communicate 而不是 wait 使用输出(我认为保留输出可为 OP 可能想要做的事情提供更大的灵活性稍后再写代码)。
    • @rchang: proc_error 总是None 除非stderr=PIPE
    猜你喜欢
    • 2015-03-29
    • 1970-01-01
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    相关资源
    最近更新 更多