subproces,Process,multiprocessing
subprocess模块
用法:
subprocess的目的就是启动一个进程并和它通信
PIPE表示的是管道,进程间的通信
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
stdin,stdout,stderr分别表示标准输入,输出,错误句柄。他们可以是PIPE,文件描述符或者文件对象,也可以是None,表示父进程继承。
如果shell为True,程序将通过shell执行。
Popen.poll() 用于检查子进程是否结束。设置并返回returncode属性。
Popen.wait() 等待子进程结束,设置并返回returncode属性。
Popen.communicate(input=None) 与子进程进程交互。向stdin发送数据,或从stdout、stderr中读取数据。communicate()返回的是一个元组tumple,(stdoutdata, stderrdata)。
注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stdin设置为PIPE。
>>> p = Popen('ls',shell=True, stdin=PIPE, stdout=PIPE)
>>> out,err = p.communicate('/home')
>>> print out
HEAD
branches
上面的stderr和stdout是分开的,可以合并
p=subprocess.Popen(“ls“, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Popen.pid 获取子进程的pid
Popen.returncode 获取进程的返回值,如果进程还没结束,返回None。
from subprocess import Popen,PIPE
p = Popen(“ifconfig -a | grep ”)
#!usr/bin/python
from subprocess import Popen,PIPE
def excute(cmd):
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
ret,err=p.communicate()
print ret
print p.returncode
上述中:comunicate通信一次之后就关闭了管道,如果和子线程频繁通信就不能用communicate
死锁:如果你使用了管道,而又不去处理管道的输出,如果子进程输出数据过多,死锁就会发生。在python2.5的环境下,输出大于4096,就会发生死锁。如果我们用p.stdout.readline或者p.communicate去清理输出,那么无论输出多少,死锁都不会发生
#!/usr/bin/python
from threading import Thread
from Queue import Queue
import subprocess
num_threads = 3
ips = ['127.0.0.1', '10.1.51.103']
q = Queue()
def pingme(i, queue):
while True:
ip = queue.get()
print "Thread {} pinging {}".format(i, ip)
ret = subprocess.call("ping -c 1 {}".format(ip),
shell=True,
stdout=open('/dev/null', 'w'), # 防止输出流太大,造成死锁,这里将输出写到'/dev/null'中去
stdin=subprocess.PIPE
)
if ret == 0:
print '{} is alive'.format(ip)
elif ret == 1:
print '{} id down'.format(ip)
queue.task_done()
# start num_threads threads
for i in range(num_threads):
t = Thread(target=pingme, args=(i, q)) # 批量创建线程
t.setDaemon(True) # 设置为守护线程 主线程A中,创建了子线程B,将A设置为守护线程,此时主线程A执行结束啦,不管子线程B是否执行完成,一并和A一起退出
t.start()
for i in ips:
q.put(i)
print "main thread waiting ..."
q.join() # 主线程A中,创建了子线程B,并在主线程中设置B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以继续向下执行。
print 'Done'
执行结果:
PsMiff@PureMastiffdeMacBook-Pro:~/git/subprocess% python -m subprocess.subp_test
main thread waiting ...
Thread 0 pinging 127.0.0.1
Thread 1 pinging 10.1.51.103
127.0.0.1 is alive
10.1.51.103 is alive
Done
这里使用了多线程,去执行pingme函数,节约了大量的时间。
使用多线程,最长执行时间的线程就是整个程序运行的总时间。
Pingme函数是这样执行的:
1. 启动的线程去执行pingme函数
2. Pingme函数会检测队列中是否有元素。如果有的话,则取出并执行ping命令。
这个队列是多个线程共享的。所以这里不使用列表。代码中的q.join()函数是阻塞当前线程。