多进程、协程、事件驱动及select poll epoll

本文详细介绍了Python中多进程的使用,包括简单示例、进程间数据交互、同步与进程池。接着讲解了协程的概念,通过yield实现简单协程,并探讨了Greenlet和Gevent库的使用。文章还深入讨论了事件驱动,特别是IO多路复用,包括select、poll和epoll的区别与应用。最后通过示例代码展示了如何使用Python的select模块和selectors模块实现并发服务器。
摘要由CSDN通过智能技术生成

多线程的使用场景

IO操作不占用CPU

计算占用cpu

python多线程不适合cpu密集型操作的任务,适合IO操作密集型的任务

多进程

简单的一个多进程例子:(用于理解对多线程方法的使用)

和线程的方法类似,下面是一个简单的多进程代码

import time, multiprocessing


def run(name):
    time.sleep(2)
    print("hello", name)


if __name__ == "__main__":
    for i in range(6):
        p = multiprocessing.Process(target=run, args=("dean",))
        p.start()

和之前学习的多线程结合在一起使用,代码如下:

import time,threading
import multiprocessing

def thread_run():
    print(threading.get_ident())   #这里表示获取线程id

def run(name):
    time.sleep(2)
    print("hello", name)
    t = threading.Thread(target=thread_run)
    t.start()

if __name__ == "__main__":
    for i in range(6):
        p = multiprocessing.Process(target=run, args=("dean",))
        p.start()

运行结果如下:

接着我们查看下面代码:

from multiprocessing import Process
import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())
    print("\n\n")

def f(name):
    info('\033[31;1mcalled from child process function f\033[0m')
    print('hello', name)

if __name__ == '__main__':
    info('\033[32;1mmain process line\033[0m')

运行结果如下:

我们这里可以看到父进程id:12204,并且会发现无论程序运行多少次都是这个,然后我们在windows任务管理器查看发现这个是pycharm的进程id.这里要记住:每一个子进程都是由父进程启动的

我们将上面代码中if __name__=”__main__”进行修改,如下:

if __name__ == '__main__':
     info('\033[32;1mmain process line\033[0m')
     p = Process(target=f, args=('bob',))
     p.start()

运行结果如下:

进程间数据的交互,实现方法

通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享

不同进程间内存不是共享的,要想实现两个进程间的数据交换,有以下方法:

Queues

使用方法和threading里的queue使用差不多

先回忆一下线程之间的数据共享,通过下面代码理解:

import threading
import queue

def func():
    q.put([22,"dean",'hello'])

if __name__=="__main__":
    q = queue.Queue()
    t = threading.Thread(target=func)
    t.start()
    print(q.get(q))

运行结果:

从上述代码可以看出线程之间的数据是共享的:父线程可以访问子线程放入的数据,如果是多进程之间呢?将代码进行修改如下,让子进程调用父进程数据:

from multiprocessing import Process
import queue

def f():
    q.put([11,None,"hello"])

if __name__=="__main__":
    q = queue.Queue()
    p = Process(target=f)
    p.start()
    print(q.get())

运行结果如下:

从这里我们也可以看出子进程是访问不到父进程的数据,我们再次将代码进行修改,写f方法的时候直接将q给线程传入,也就是,只有启动线程,就自动传入线程q,代码如下:

from multiprocessing import Process
import queue

def f(data):
    data.put([11,None,"hello"])

if __name__=="__main__":
    q = queue.Queue()   #切记这里是线程q
    p = Process(target=f,args=(q,))
    p.start()
    print(q.get())

运行结果如下:

这里我们需要知道:进程不能访问线程q,所以我们需要改成进程,代码如下:

from multiprocessing import Process,Queue

def f(data):
    data.put([11,None,"hello"])

if __name__=="__main__":
    q = Queue()    #这里的q是进程q
    p = Process(target=f,args=(q,))
    p.start()
    print(q.get())

运行结果:

这次我们就发现在父进程里就可以调用到子进程放入的数据

这里我们需要明白:这里的q其实是被克隆了一个q,然后将子线程序列化的内容传入的克隆q,然后再反序列化给q,从而实现了进程之间数据的传递

Pipe

实现代码例子:

from multiprocessing import Process,Pipe

def f(conn):
    conn.send([22,None,"hello from child"])
    conn.send([22,None,"hello from child2"])
    print(conn.recv())
    conn.close()

if __name__=="__main__":
    left_conn,right_conn = Pipe()
    p = Process(target=f,args=(right_conn,))
    p.start()
    print(left_conn.recv())
    print(left_conn.recv
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值