python进程模块-subprocess,Process,multiprocessing

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()函数是阻塞当前线程。

参考链接:https://blog.csdn.net/imzoer/article/details/8678029

猜你喜欢

转载自blog.csdn.net/lovegengxin/article/details/80334817