• python第五十三天--进程,协程.select.异步I/O...


    进程:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 import multiprocessing,threading,time
     5 
     6 def run(name):
     7     t=threading.Thread(target=run2)#创建新线程
     8     t.start()
     9     print('进程[%s],打印中...'%name)
    10     time.sleep(1)
    11 
    12 def run2():
    13     print(threading.get_ident())#打印线程ID
    14     time.sleep(2)
    15 
    16 
    17 if __name__ == '__main__':
    18     for i in range(10):
    19         p=multiprocessing.Process(target=run,args=('第[%s]个进程'%i,))#创建新进程
    20         p.start()
    View Code

    进程号:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 
     5 import  multiprocessing,threading,time,os
     6 from  multiprocessing import Process#从 multprocessing 打开 Process
     7 def info_l(file):
     8     print('当前模块名:',__name__)
     9     print('父进程ID:',os.getppid())
    10     print('进程ID:',os.getpid())
    11     print('
    
    ')
    12 
    13 def f(name):
    14     print('查看:',name)
    15     info_l('相关列表')
    16 
    17 
    18 if __name__ == '__main__':
    19     info_l('主进程相关列表')
    20     p=Process(target=f,args=('当前进程',))
    21     p.start()
    22     p.join()
    View Code

    进程锁:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 
     5 from multiprocessing import Process,Lock # Lock 进程锁通讯中间件
     6 
     7 def f(lock,i):
     8     lock.acquire()#进程锁
     9     print('第[%s]个进程'%i)
    10     lock.release()#解锁
    11 if __name__ =='__main__':
    12     lock=Lock()#进程锁对象
    13     for i in range(10):
    14         p=Process(target=f,args=(lock,i)).start()
    View Code

    进程之间通讯:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 
     5 import multiprocessing,queue,threading
     6 from multiprocessing import Process,Queue # Queue 进程通讯中间件
     7 
     8 
     9 '''  线程 之间共享队列
    10 def f():
    11     q.put([1,None,'加入数据'])#队列
    12 if __name__ =='__main__':
    13     q=queue.Queue()#线程队列
    14     #q=Queue()#进程队列
    15     p=threading.Thread(target=f,)#创建线程
    16     p.start()
    17     print(q.get())#输出,取出的
    18     p.join()
    19 '''
    20 def f(q):#存入q对象
    21     q.put([1,None,'加入数据'])#队列
    22 if __name__ =='__main__':
    23     q=Queue()#进程队列
    24     p=Process(target=f,args=(q,))#创建进程
    25     p.start()
    26     print(q.get())#输出,取出的
    27     p.join()
    View Code
     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 import os
     5 from multiprocessing import Process,Pipe,Manager # Pipe 管道 进程通讯中间件
     6 
     7 
     8 def f(d,l):
     9     d[os.getpid()]=os.getpid()#修改字典
    10     l.append(os.getpid())#添加列表内容
    11     print(d)
    12     print(l)
    13 
    14 
    15 if __name__ =='__main__':
    16     with Manager() as manager:
    17         d=manager.dict()#创建一个进程之间可修改的字典
    18         l=manager.list(range(5))#创建一个进程之间可修改的列表
    19         p_list=[]#join使用
    20         for i in range(10):
    21             p=Process(target=f,args=(d,l))#创建进程传入数据,
    22             p.start()
    23             p_list.append(p)
    24         for r in p_list:#等待进程完成
    25             r.join()
    26         print(d)
    27         print(l)
    View Code
     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan
     4 
     5 from multiprocessing import Process,Pipe # Pipe 管道 进程通讯中间件
     6 
     7 def f(conn):#存入conn对象
     8     conn.send(['子进程发送信息','....'])
     9     print('收到父进程的信息:',conn.recv())
    10     conn.close()
    11 if __name__ =='__main__':
    12     parent_conn,child_conn=Pipe()#生成一个管道,返回两个值,管理双端
    13     p=Process(target=f,args=(child_conn,))#创建进程
    14     p.start()
    15     print('收到子进程的信息:',parent_conn.recv())
    16     parent_conn.send(['父进程发送信息'])
    17     p.join()
    View Code

    进程池:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #__author__=2017/6/23
     5 import time,os
     6 from multiprocessing import Process,Lock,Pool # Pool 进程池通讯中间件
     7 
     8 def Foo(i):
     9     print('第[%s]个进程,ID:'%i,os.getpid())
    10     time.sleep(3)
    11     return i+100
    12 def Bar(arg):
    13     print('回调>>>>:',arg,os.getpid())
    14 if __name__ =='__main__':
    15     #pool=Pool(processes=5)#定义一个进程池 表示允许进程池同时放入5个进程
    16     pool=Pool(5)#定义一个进程池 表示允许进程池同时放入5个进程
    17     for i in range(10):
    18         #pool.apply(func=Foo,args=(i,))#使用进程池创建进程  串行
    19         #pool.apply_async(func=Foo,args=(i,))#使用进程池创建进程 并行
    20         pool.apply_async(func=Foo,args=(i,),callback=Bar)#回调
    21 
    22     print('结束')
    23     #pool.join()
    24     pool.close()#一定要先关闭进程池
    25     pool.join()#后进行join
    View Code

    协程:

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    10:10
     6 #__author__='Administrator'
     7 
     8 import time
     9 import queue
    10 def consumer(name):#消费者函数
    11     print('[%s]消费产品中.......'%name)
    12     while True:
    13         new_b=yield #跳转点
    14         print('[%s] 消费 [%s]'%(name,new_b))
    15 def producer():#生产者函数
    16     r=con.__next__()
    17     r2=con2.__next__()
    18     n=0
    19     while n<10:
    20         n+=1
    21         con.send(n)#发送给消费者
    22         con2.send(n)
    23         print('33[32;1m[生产者]33[0m生产产品[%s]'%n)
    24 
    25 if __name__=='__main__':
    26     con=consumer('消费者A')
    27     con2=consumer('消费者B')
    28     p=producer()
    View Code
     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    10:31
     6 #__author__='Administrator'
     7 #import greenlet
     8 from greenlet import greenlet
     9 
    10 def test1():
    11     print('函数一: 12')
    12     ger2.switch()#进行协程切换
    13     print('函数一: 34')
    14     ger2.switch()
    15 
    16 def test2():
    17     print('函数二: 56')
    18     ger1.switch()
    19     print('函数二: 78')
    20     ger1.switch()
    21 
    22 ger1=greenlet(test1)#创建协程
    23 ger2=greenlet(test2)
    24 ger1.switch()
    View Code
     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    10:47
     6 #__author__='Administrator'
     7 
     8 import gevent
     9 def func1():
    10     print('func1 reading....')
    11     gevent.sleep(2)
    12     print('func1 reading two.. end')
    13 
    14 def func2():
    15     print('func2 reading....')
    16     gevent.sleep(0)
    17     print('func2 reading two.. end')
    18 def func3():
    19     print('func3 reading....')
    20     gevent.sleep(1)
    21     print('func3 reading two.. end')
    22 
    23 gevent.joinall([
    24     gevent.spawn(func1),
    25     gevent.spawn(func2),
    26     gevent.spawn(func3)
    27 ])
    View Code

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    14:03
     6 #__author__='Administrator'
     7 from urllib import request
     8 import gevent,time
     9 from gevent import monkey
    10 monkey.patch_all()#对所有的I/O操作进行标记
    11 
    12 def f(url):#爬取网页
    13     print('网址: ',url)
    14     resp=request.urlopen(url)#打开网页
    15     data=resp.read()#读取网页
    16     print('网址:[%s]的网页数据大小:[%s]'%(url,len(data)))
    17 
    18 urls=['https://www.python.org/',
    19       'https://hao.360.cn/',
    20       'https://www.yahoo.com/']
    21 
    22 time_start=time.time()#同步 串行开始时间
    23 for url in urls:
    24     f(url)
    25 print('同步时长:',time.time()-time_start)
    26 
    27 time_start_asy=time.time()#异步 并行开始时间
    28 gevent.joinall([
    29     gevent.spawn(f,'https://www.python.org/'),
    30     gevent.spawn(f,'https://hao.360.cn/'),
    31     gevent.spawn(f,'https://www.yahoo.com/')
    32 ])
    33 print('异域步时长:',time.time()-time_start_asy)
    View Code

    协程socket_server 实现并发

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    14:42
     6 #__author__='Administrator'
     7 
     8 import sys
     9 import socket
    10 import time
    11 import gevent
    12 
    13 from gevent import socket,monkey
    14 monkey.patch_all()
    15 
    16 
    17 def server(port):
    18     s = socket.socket()#socket 对象
    19     s.bind(('0.0.0.0', port))#服务端,bind IP 端口
    20     s.listen(500)
    21     print('监听中....')
    22     while True:
    23         cli, addr = s.accept()
    24         gevent.spawn(handle_request, cli)#创建一个新协程来
    25 
    26 
    27 
    28 def handle_request(conn):
    29     try:
    30         while True:
    31             data = conn.recv(1024)
    32             print("recv:", data)
    33             conn.send(data)
    34             if not data:
    35                 conn.shutdown(socket.SHUT_WR)
    36 
    37     except Exception as  ex:
    38         print(ex)
    39     finally:
    40         conn.close()
    41 if __name__ == '__main__':
    42     server(8001)
    View Code

    select :

    socket_server

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    19:34
     6 #__author__='Administrator'
     7 
     8 import select,socket,sys ,queue
     9 
    10 s=socket.socket()#实例化一个连接对象
    11 s.setblocking(0)#设置成非阻塞
    12 server_addr=('localhost',9500)#设置绑定的 IP 端口
    13 s.bind(server_addr)#连接对象绑定IP 端口
    14 s.listen(100)#队列  可连接数量
    15 inputs=[s,]#首先要监测本身
    16 
    17 outputs=[]#发送列表
    18 
    19 meg_queues={} #发送 连接对象的队列集合  字典
    20 
    21 while True:
    22     print('监听中......')
    23     readable,writeable,exeptional=select.select(inputs,outputs,inputs)#生成select 对象,返回三个列表 连接,发关,错误
    24 
    25     for i in readable: #i为一个socket
    26         if i is s:#如果i 是s 表示有新 连接 进来
    27             conn,client_addr=i.accept()#建立一个新连接
    28             print('接入一个新连接...',client_addr)
    29             conn.setblocking(0)#也设成非阻塞
    30             inputs.append(conn)#加入select,的连接列表,避免出现阻塞
    31             meg_queues[conn]=queue.Queue()#创建一个队列  添加到字典
    32         else:
    33             try:
    34                 data=i.recv(1024)#如果不是新连接就收数据
    35             except Exception as e:
    36                 print(e)
    37             if data: #如果数据不为空
    38                 print('[%s] 发来的数据 [%s]'%(i.getpeername,data))
    39                 meg_queues[i].put(data)#当前连接的消息队列加入数据
    40                 if i not in outputs:#如果当前连接没有在发送列表内,就加入发送列表
    41                     outputs.append(i)
    42             else:
    43                 print('客户端已经断开了....')#开始清理工作
    44                 if i in outputs:#在发送列表
    45                     outputs.remove(i)#在发送列表内删除
    46                 inputs.remove(i)#在连接列表内删除
    47                 del meg_queues[i]#在队列字典内删除
    48 
    49     for w in writeable:#循环发送列表
    50         try:
    51             msg=meg_queues[w].get_nowait()#取出队列中的数据,判断
    52         except queue.Empty:#如果数据为空
    53             outputs.remove(w)##从发送列表内删除
    54         else:
    55             w.send(msg)#发送
    56 
    57     for e in exeptional:#循环错误列表
    58         print('连接[%s]出错!'%e.getpeername)
    59         inputs.remove(e)##从发送列表内删除
    60         if e in outputs:#在发送列表
    61             outputs.remove(e)#在发送列表内删除
    62         e.close()
    63         del meg_queues[e]#在队列字典内删除
    View Code

    socket_client

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    19:23
     6 #__author__='Administrator'
     7 
     8 import socket
     9 
    10 server_addr=('localhost',9500)#设置绑定的 IP 端口
    11 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    12 s.connect(server_addr)
    13 while True:
    14     msg = bytes(input(">>:"),encoding="utf8")#定义一个数据 消息
    15     if msg:
    16         s.sendall(msg)#发送数据
    17     else:
    18         print('不能为空')
    19         continue
    20     data = s.recv(1024)#收数据(读数据)
    21     #print(data)
    22 
    23     print('Received', repr(data.decode()))
    24 s.close()
    View Code

    selectors :

     1 #!usr/bin/env python
     2 #-*-coding:utf-8-*-
     3 # Author calmyan 
     4 #python 
     5 #2017/6/24    21:58
     6 #__author__='Administrator'
     7 import selectors
     8 import socket
     9 
    10 sel = selectors.DefaultSelector()#生成一个创建一个selectors对象
    11 
    12 def accept(sock, mask):
    13     conn, addr = sock.accept()  # 建立新连接
    14     print('accepted', conn, 'from', addr)
    15     conn.setblocking(False)#设成非阻塞
    16     sel.register(conn, selectors.EVENT_READ, read)#注册 连接,回调函数 read
    17 
    18 def read(conn, mask):
    19     data = conn.recv(1024)  # 接收数据
    20     if data:#不为空
    21         print('echoing', repr(data), 'to', conn)
    22         conn.send(data)  # 发送数据
    23     else:#如果为空
    24         print('closing', conn)
    25         sel.unregister(conn)#取消注册
    26         conn.close()#关闭连接
    27 
    28 server_addr=('localhost',9501)#设置绑定的 IP 端口
    29 sock = socket.socket()#创建一个sock对象
    30 sock.bind(server_addr)#绑定IP 端口
    31 sock.listen(100)
    32 print('监听中...')
    33 sock.setblocking(False)#非阻塞
    34 sel.register(sock, selectors.EVENT_READ, accept)#注册连接  返调函数为accept
    35 
    36 while True:
    37     events = sel.select()#默认为阻塞模式
    38     for key, mask in events:#如果有连接,接入
    39         callback = key.data#新建连接句柄
    40         callback(key.fileobj, mask)
    View Code

    事件驱动与异步IO

    服务器处理模型的程序时,有以下几种模型:
    (1)每收到一个请求,创建一个新的进程,来处理该请求;
    (2)每收到一个请求,创建一个新的线程,来处理该请求;
    (3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
     
    第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。
    第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。
    第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。
    综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网络服务器采用的方式
     
    事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。
  • 相关阅读:
    《Metasploit 渗透测试魔鬼训练营》 攻击机无法攻击靶机
    Ubuntu 解压 RAR
    verilog实验2:基于FPGA的59秒计时器设计
    verilog实验1:基于FPGA蜂鸣器演奏乐曲并数码管显示
    Java基础之反射和动态代理
    Redis初探
    Rest(表述性状态转移)
    深入理解MVC模式
    @Controller和@RestController的区别
    solrconfig.xml和schema.xml说明
  • 原文地址:https://www.cnblogs.com/uge3/p/7074807.html
Copyright © 2020-2023  润新知