Python笔记day39(并发)|回调函数爬虫例子、多线程、多线程socket聊天

1,内容回顾
# 今天和明天  多线程
# 协程 + IO模型

# 管道
# 数据的共享 Manager dict list
# 进程池
    # cpu个数+1
    # ret = map(func,iterable)
        # 异步 自带close和join
        # 所有结果的[]
    # apply
        # 同步的:只有当func执行完之后,才会继续向下执行其他代码
        # ret = apply(func,args=())
        # 返回值就是func的return
    # apply_async
        # 异步的:当func被注册进入一个进程之后,程序就继续向下执行
        # apply_async(func,args=())
        # 返回值 : apply_async返回的对象obj
        #          为了用户能从中获取func的返回值obj.get()
        # get会阻塞直到对应的func执行完毕拿到结果
        # 使用apply_async给进程池分配任务,
        # 需要先close后join来保持多进程和主进程代码的同步性
1)回调函数
# 回调函数是在主进程中执行的
from multiprocessing import Pool
def func1(n):
    return n+1

def func2(m):
    print(m)

if __name__ == '__main__':
    p = Pool(5)
    for i in  range(10,20):
        p.apply_async(func1,args=(i,),callback=func2)
    p.close()
    p.join()
2)爬虫简单例子
import requests
from urllib.request import urlopen
from multiprocessing import Pool
# 200 网页正常的返回
# 404 网页找不到
# 502 504
def get(url):
    response = requests.get(url)
    if response.status_code == 200:
        return url,response.content.decode('utf-8')

def get_urllib(url):
    ret = urlopen(url)
    return ret.read().decode('utf-8')

def call_back(args):
    url,content = args
    print(url,len(content))

if __name__ == '__main__':
    url_lst = [
        'https://www.cnblogs.com/',
        'http://www.baidu.com',
        'https://www.sogou.com/',
        'http://www.sohu.com/',
    ]
    p = Pool(5)
    for url in url_lst:
        p.apply_async(get,args=(url,),callback=call_back)
    p.close()
    p.join()
3)爬取猫眼电影例子
import re
from urllib.request import urlopen
from multiprocessing import Pool

def get_page(url,pattern):
    response=urlopen(url).read().decode('utf-8')
    return pattern,response   # 正则表达式编译结果 网页内容

def parse_page(info):
    pattern,page_content=info
    res=re.findall(pattern,page_content)
    for item in res:
        dic={
            'index':item[0].strip(),
            'title':item[1].strip(),
            'actor':item[2].strip(),
            'time':item[3].strip(),
        }
        print(dic)
if __name__ == '__main__':
    regex = r'<dd>.*?<.*?class="board-index.*?>(\d+)</i>.*?title="(.*?)".*?class="movie-item-info".*?<p class="star">(.*?)</p>.*?<p class="releasetime">(.*?)</p>'
    pattern1=re.compile(regex,re.S)
    url_dic={'http://maoyan.com/board/7':pattern1}
    p=Pool()
    res_l=[]
    for url,pattern in url_dic.items():
        res=p.apply_async(get_page,args=(url,pattern),callback=parse_page)
        res_l.append(res)

    for i in res_l:
        i.get()

2,线程
# 进程 是 最小的 内存分配单位
# 线程 是 操作系统调度的最小单位
# 线程直接被CPU执行,进程内至少含有一个线程,也可以开启多个线程
    # 开启一个线程所需要的时间要远远小于开启一个进程
    # 多个线程内部有自己的数据栈,数据不共享
    # 全局变量在多个线程之间是共享的
# GIL锁(即全局解释器锁)
# 在Cpython解释器下的python程序 在同一时刻 多个线程中只能有一个线程被CPU执行
# 高CPU (不适合多线程): 计算类 --- 高CPU利用率
# 高IO  (适合多线程): 爬取网页 200个网页
        # qq聊天   send recv
        # 处理日志文件 读文件
        # 处理web请求
        # 读数据库 写数据库
使用线程的两种方法
import os
import time
from threading import Thread
 多线程并发
 def func(a,b):
     global g
     g = 0
     print(g,os.getpid())

 g = 100
 t_lst = []
 for i in range(10):
     t = Thread(target=func,args=(i,5))
     t.start()
     t_lst.append(t)
 for t in  t_lst : t.join()
 print(g)
 class MyTread(Thread):
     def __init__(self,arg):
         super().__init__()
         self.arg = arg
     def run(self):
         time.sleep(1)
         print(self.arg)

 t = MyTread(10)
 t.start()
比较多线程和多进程的效率

import time
from threading import Thread
from multiprocessing import Process
def func(n):
    n + 1

if __name__ == '__main__':
    start = time.time()
    t_lst = []
    for i in range(100):
        t = Thread(target=func,args=(i,))
        t.start()
        t_lst.append(t)
    for t in t_lst:t.join()
    t1 = time.time() - start

    start = time.time()
    t_lst = []
    for i in range(100):
        t = Process(target=func, args=(i,))
        t.start()
        t_lst.append(t)
    for t in t_lst: t.join()
    t2 = time.time() - start
    print(t1,t2)

线程模块中其他方法
import time
import threading

def wahaha(n):
    time.sleep(0.5)
    print(n,threading.current_thread(),threading.get_ident())

for i in  range(10):
    threading.Thread(target=wahaha,args=(i,)).start()
print(threading.active_count())    # 10
print(threading.current_thread())
print(threading.enumerate())


3,多线程socket聊天

server端代码

import socket
from threading import Thread

def chat(conn):
    conn.send(b'hello')
    msg = conn.recv(1024).decode('utf-8')
    print(msg)
    conn.close()

sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
while True:
    conn,addr = sk.accept()
    Thread(target=chat,args = (conn,)).start()
sk.close()

client端代码

import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))

msg = sk.recv(1024)
print(msg)
inp = input('>>> ').encode('utf-8')
sk.send(inp)
sk.close()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值