今天花了点时间了解了管道的相关知识,学会了实时获取管道信息的方式,通过这种方式,我可以很简单的将subprocess.Popen()中的标准输出实时获取到,进而利用这些实时信息实现更灵活更强大的功能。
废话不多说,代码如下:
import subprocess import threading import time string = '"/Applications/Nuke10.0v4/NukeX10.0v4.app/../Nuke10.0v4.app/Contents/MacOS/Nuke10.0v4" -t -F 1-100 -m 4 -x /Users/SolHe/Downloads/test.nk' f = subprocess.Popen(string, shell=True, stdout=subprocess.PIPE) def check(): oldcontent = "" while 1: f.stdout.flush() newcontent = f.stdout.readline() if oldcontent != newcontent: print newcontent oldcontent = newcontent if f.poll() == 0: print "finish" break return g = threading.Thread(target=check) g.start() g.join()
首先建立一个子进程f,该进程执行外部程序,启动nuke的渲染;再建立一个线程g,该线程执行check()函数来实时获取f进程的标准输出,而获取实时输出的关键在于f.stdout.flush(),只有每次首先利用flush清空标准输出的缓存空间,才能获取到实时的信息。如果不做清空,那么stdout是有缓存结束才会返回管道信息,这样就不实时了。所以在这里想要实时,就必须手动清空缓存。
在这里再附上一个关于多进程库multyprocessing的小案例mark一下:
from multiprocessing import Process, Pipe def send(pipe): "send" pipe.send(['spam'] + [42, 'egg']) pipe.close() def talk(pipe): "talk" pipe.send(dict(name='Bob', spam=42)) reply = pipe.recv() print('talker got:', reply) if __name__ == '__main__': con1, con2 = Pipe() sender = Process(target=send, name='send', args=(con1,)) sender.start() print "con2 got: %s" % con2.recv()#从send收到消息 con2.close() (parentEnd, childEnd) = Pipe() child = Process(target = talk, name = 'talk', args = (childEnd,)) child.start() print('parent got:', parentEnd.recv()) parentEnd.send({x * 2 for x in 'spam'}) child.join() print('parent exit')
这个案例就不做过度解释了,非常简单,利用了管道这种特性实现了信息交互,以后写高并发程序的时候非常有用。
关于管道和进程的知识还得多学习,以上。