前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3--进程,线程,协程效率对比

python3--进程,线程,协程效率对比

作者头像
py3study
发布2018-08-02 17:50:22
1.3K0
发布2018-08-02 17:50:22
举报
文章被收录于专栏:python3python3python3

需求:写一个脚本,判断192.168.11.0/24网络里,当前在线ip有哪些?

知识点:

1 使用subprocess模块,来调用系统命令,执行ping 192.168.11.xxx 命令

2 调用系统命令执行ping命令的时候,会有返回值(ping的结果),需要用到stdout=fnull, stderr=fnull方法,屏蔽系统执行命令的返回值

常规版本(代码)

import os
import time
import subprocess
def ping_call():
    start_time = time.time()
    fnull = open(os.devnull, 'w')
    for i in range(1, 256):
        ipaddr = 'ping 192.168.11.' + str(i)
        result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)
        current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())
        if result:
            print('时间:{} ip地址:{} ping fall'.format(current_time, ipaddr))
        else:
            print('时间:{} ip地址:{} ping ok'.format(current_time, ipaddr))
    print('程序耗时{:.2f}'.format(time.time() - start_time))
    fnull.close()
ping_call()

执行效果:

blob.png
blob.png

上面的执行速度非常慢,怎么能让程序执行速度快起来?

python提供了进程,线程,协程。分别用这三个对上面代码改进,提高执行效率,测试一波效率

进程池异步执行 -- 开启20个进程

import os
import time
import subprocess
from multiprocessing import Pool
def ping_call(num):
    fnull = open(os.devnull, 'w')
    ipaddr = 'ping 192.168.11.' + str(num)
    result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)
    current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())
    if result:
        print('时间:{} ip地址:{} ping fall'.format(current_time, ipaddr))
    else:
        print('时间:{} ip地址:{} ping ok'.format(current_time, ipaddr))

    fnull.close()


if __name__ == '__main__':
    start_time = time.time()
    p = Pool(20)
    res_l = []
    for i in range(1, 256):
        res = p.apply_async(ping_call, args=(i,))
        res_l.append(res)
    for res in res_l:
        res.get()
    print('程序耗时{:.2f}'.format(time.time() - start_time))

执行结果:

blob.png
blob.png

线程池异步执行 -- 开启20个线程

import os
import time
import subprocess
from concurrent.futures import ThreadPoolExecutor
def ping_call(num):
    fnull = open(os.devnull, 'w')
    ipaddr = 'ping 192.168.11.' + str(num)
    result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)
    current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())
    if result:
        print('时间:{} ip地址:{} ping fall'.format(current_time, ipaddr))
    else:
        print('时间:{} ip地址:{} ping ok'.format(current_time, ipaddr))
    fnull.close()

if __name__ == '__main__':
    start_time = time.time()
    thread_pool = ThreadPoolExecutor(20)
    ret_lst = []
    for i in range(1, 256):
        ret = thread_pool.submit(ping_call, i)
        ret_lst.append(ret)
    thread_pool.shutdown()
    for ret in ret_lst:
        ret.result()
    print('线程池(20)异步-->耗时{:.2f}'.format(time.time() - start_time))

执行结果:

blob.png
blob.png

协程执行---(执行多个任务,遇到I/O操作就切换)

使用gevent前,需要pip install gevent

from gevent import monkey;monkey.patch_all()
import gevent
import os
import time
import subprocess

def ping_call(num):
    fnull = open(os.devnull, 'w')
    ipaddr = 'ping 192.168.11.' + str(num)
    result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)
    current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())
    if result:
        print('时间:{} ip地址:{} ping fall'.format(current_time, ipaddr))
    else:
        print('时间:{} ip地址:{} ping ok'.format(current_time, ipaddr))
    fnull.close()

def asynchronous(): # 异步
    g_l = [gevent.spawn(ping_call, i) for i in range(1, 256)]
    gevent.joinall(g_l)

if __name__ == '__main__':
    start_time = time.time()
    asynchronous()
    print('协程执行-->耗时{:.2f}'.format(time.time() - start_time))

执行结果:

blob.png
blob.png

遇到I/O操作,协程的效率比进程,线程高很多!

总结:python中,涉及到I/O阻塞的程序中,使用协程的效率最高

最后附带协程池代码

gevent.pool

from gevent import monkey;monkey.patch_all()
import gevent
import os
import time
import subprocess
import gevent.pool

def ping_call(num):
    fnull = open(os.devnull, 'w')
    ipaddr = 'ping 192.168.11.' + str(num)
    result = subprocess.call(ipaddr + ' -n 2', shell=True, stdout=fnull, stderr=fnull)
    current_time = time.strftime('%Y%m%d-%H:%M:%S', time.localtime())
    if result:
        print('时间:{} ip地址:{} ping fall'.format(current_time, ipaddr))
    else:
        print('时间:{} ip地址:{} ping ok'.format(current_time, ipaddr))
    fnull.close()

if __name__ == '__main__':
    start_time = time.time()
    res_l = []
    p = gevent.pool.Pool(100)
    for i in range(1, 256):
        res_l.append(p.spawn(ping_call, i))
    gevent.joinall(res_l)
    print('协程池执行-->耗时{:.2f}'.format(time.time() - start_time))

执行结果:

blob.png
blob.png
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档