p=subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE)
stdoutput,erroutput = p.communicate('/home/zoer')
print stdoutput[0]
print erroutput
上面的例子通过communicate给stdin发送数据,然后使用一个tuple接收命令的执行结果。
上面,标准输出和标准错误输出是分开的,也可以合并起来,只需要将stderr参数设置为subprocess.STDOUT就可以了,这样子:
p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(stdoutput,erroutput) = p.communicate()
如果你想一行行处理子进程的输出,也没有问题:
p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
buff = p.stdout.readline()
if buff == '' and p.poll() != None:
break
但是如果你使用了管道,而又不去处理管道的输出,那么小心点,如果子进程输出数据过多,死锁就会发生了,比如下面的用法:
p=subprocess.Popen("longprint", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p.wait()
longprint是一个假想的有大量输出的进程,那么在我的xp, Python2.5的环境下,当输出达到4096时,死锁就发生了。当然,如果我们用p.stdout.readline或者p.communicate去清理输出,那么无论输出多少,死锁都是不会发生的。或者我们不使用管道,比如不做重定向,或者重定向到文件,也都是可以避免死锁的。
subprocess还可以连接起来多个命令来执行。
在shell中我们知道,想要连接多个命令可以使用管道。
在subprocess中,可以使用上一个命令执行的输出结果作为下一次执行的输入。例子如下:
p1=subprocess.Popen('cat ff',shell=True,stdout=subprocess.PIPE)
p2=subprocess.Popen('tail -2',shell=True,stdin=p1.stdout,stdout=subprocess.PIPE)
print p2.stdout
print p2.stdout.read()
例子中,p2使用了第一次执行命令的结果p1的stdout作为输入数据,然后执行tail命令。
ip=queue.get()
print 'Thread %s pinging %s' %(i,ip)
ret=subprocess.call('ping -c 1 %s' % ip,shell=True,stdout=open('/dev/null','w'),stderr=subprocess.STDOUT)
if ret==0:
print '%s is alive!' %ip
elif ret==1:
print '%s is down...'%ip
queue.task_done()
#start num_threads threads
for i in range(num_threads):
t=Thread(target=pingme,args=(i,q))
t.setDaemon(True)
t.start()
for ip in ips:
q.put(ip)
print 'main thread waiting...'
q.join();print 'Done'
在上面代码中使用subprocess的主要好处是,使用多个线程来执行ping命令会节省大量时间。
假设说我们用一个线程来处理,那么每个 ping都要等待前一个结束之后再ping其他地址。那么如果有100个地址,一共需要的时间=100*平均时间。
如果使用多个线程,那么最长执行时间的线程就是整个程序运行的总时间。【时间比单个线程节省多了】
这里要注意一下Queue模块的学习。
pingme函数的执行是这样的:
启动的线程会去执行pingme函数。
pingme函数会检测队列中是否有元素。如果有的话,则取出并执行ping命令。
这个队列是多个线程共享的。所以这里我们不使用列表。【假设在这里我们使用列表,那么需要我们自己来进行同步控制。Queue本身已经通过信号量做了同步控制,节省了我们自己做同步控制的工作=。=】
代码中q的join函数是阻塞当前线程。下面是e文注释
Queue.join()
Blocks until all items in the queue have been gotten and processed(task_done()).
学习Processing模块的时候,遇到了进程的join函数。进程的join函数意思说,等待进程运行结束。与这里的Queue的join有异曲同工之妙啊。
processing模块学习的文章在这里
。