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 = [
'',
'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()