python单线程解决并发

Posted Apollo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python单线程解决并发相关的知识,希望对你有一定的参考价值。

1.单线程解决并发

方式一

import socket
import select

# 百度创建连接:非阻塞
client1 = socket.socket()
client1.setblocking(False)
try:
    client1.connect(('www.baidu.com', 80))
except BlockingIOError as e:
    pass

# 搜狗创建连接:非阻塞
client2 = socket.socket()
client2.setblocking(False)
try:
    client2.connect(('www.sogou.com', 80))
except BlockingIOError as e:
    pass

# GitHub创建连接:非阻塞
client3 = socket.socket()
client3.setblocking(False)
try:
    client3.connect(('www.github.com', 80))
except BlockingIOError as e:
    pass

# 创建socket列表:socket_list
socket_list = [client1, client2, client3]
# 创建connect列表:conn_list
conn_list = [client1, client2, client3]

while True:
    rlist, wlist, elist = select.select(socket_list, conn_list, [], 0.005)
    # rlist中表示已近获取数据的socket对象
    # wlist中表示已经连接成功的socket对象
    # elist中表示出现错误的socket对象
    for sk in wlist:
        if sk == client1:
            sk.sendall(b'GET /s?wd=alex HTTP/1.0
host:www.baidu.com

')
        elif sk == client2:
            sk.sendall(b'GET /web?query=fdf HTTP/1.0
host:www.sogou.com

')
        else:
            sk.sendall(b'GET /s?wd=alex HTTP/1.0
host:www.oldboyedu.com

')
        conn_list.remove(sk)
    for sk in rlist:
        chunk_list = []
        while True:
            try:
                chunk = sk.recv(8096)
                if not chunk:
                    break
                chunk_list.append(chunk)
            except BlockingIOError as e:
                break
        body = b''.join(chunk_list)
        # print(body.decode('utf-8'))
        print('------------>', body)
        sk.close()
        socket_list.remove(sk)
    if not socket_list:
        break

方式二

import socket
import select

class Req(object):
    def __init__(self,sk,func):
        self.sock = sk
        self.func = func

    def fileno(self):
        return self.sock.fileno()


class Nb(object):

    def __init__(self):
        self.conn_list = []
        self.socket_list = []

    def add(self,url,func):
        # 创建socket客户端
        client = socket.socket()
        # 非阻塞
        client.setblocking(False)
        try:
            # 创建连接
            client.connect((url, 80))
            # 异常处理
        except BlockingIOError as e:
            pass
        obj = Req(client,func)
        # 连接列表
        self.conn_list.append(obj)
        # socket列表
        self.socket_list.append(obj)

    def run(self):

        while True:
            rlist,wlist,elist = select.select(self.socket_list,self.conn_list,[],0.005)
            # wlist中表示已经连接成功的req对象
            for sk in wlist:
                # 发生变换的req对象
                sk.sock.sendall(b'GET /s?wd=alex HTTP/1.0
host:www.baidu.com

')
                self.conn_list.remove(sk)
            for sk in rlist:
                chunk_list = []
                while True:
                    try:
                        chunk = sk.sock.recv(8096)
                        if not chunk:
                            break
                        chunk_list.append(chunk)
                    except BlockingIOError as e:
                        break
                body = b''.join(chunk_list)
                # print(body.decode('utf-8'))
                sk.func(body)
                sk.sock.close()
                self.socket_list.remove(sk)
            if not self.socket_list:
                break


def baidu_repsonse(body):
    print('百度下载结果:',body)

def sogou_repsonse(body):
    print('搜狗下载结果:', body)

def github_repsonse(body):
    print('GITHUB下载结果:', body)


t1 = Nb()
t1.add('www.baidu.com',baidu_repsonse)
t1.add('www.sogou.com',sogou_repsonse)
t1.add('www.github.com',oldboyedu_repsonse)
t1.run()

以上是关于python单线程解决并发的主要内容,如果未能解决你的问题,请参考以下文章

单线程解决高并发的思路

Python来实现并发的Web Server,其中采用了多进程多线程协程单进程单线程非阻塞的方式

解决SpringBoot定时任务并发执行线程单例问题

解决SpringBoot定时任务并发执行线程单例问题

python全栈脱产第37天------进程池与线程池协程gevent模块单线程下实现并发的套接字通信

Python3-gevent模块-单线程下的"并发"-协程