python进阶--月考五
(一)使用socket和多线程,实现支持多人对话的聊天室
1.实现服务端server中Manager类,实现管理员进入和离开聊天室,接受成员消息并广播
2.实现客户端client中Chatter类,实现向管理员发送加入和退出的请求,发送和接受消息
3.Manager类需要使用多线程服务多个用户
4.Chatter类需要使用多线程进行发送接受消息
5.Manager类具有定向转发功能,比如Chatter可以在消息中通过@指定用户,这样Manager将只把消息转发给对应用户
6.Chatter离开时,自动将聊天室保存到本地记录client.log中,包括时间,发信人,发送信息
7.Manger同时需要将信息存入到本地的mysql中
8.正确连接本地mysql,表自定义
import socket
import threading,datetime,pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='12345678',
db='test_m4'
)
cursor = conn.cursor()
#服务器端的类
class Manager():
users = {} # 建群
def msg(self,client):
while True:
#发件人【0】@收件人【1】@消息【2】
str1 = client.recv(1024).decode()
if str1:
print(str1)
send_str = int(str1.split('@')[0]) #发件人
recv_str = int(str1.split('@')[1]) #收件人
msg_str = str1.split('@')[2] #消息
# 离开
if msg_str == 'bye':
self.users.pop(send_str) # 踢人
print(f'{send_str}客户端已退出')
# 存聊天记录
sql = f"insert msg(send_name,recv_name,message,s_time) VALUES('{send_str}','{recv_str}','{msg_str}','{datetime.datetime.now()}')"
cursor.execute(sql)
conn.commit()
# 群聊
if recv_str == 0:
for i in self.users.values():
i.send(f'{send_str}:{msg_str}'.encode())
else:
#私聊 收件人
self.users.get(recv_str).send(f'{send_str}:{msg_str}'.encode())
def create_server(self):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 7007))
server.listen(128)
while True:
client, ip = server.accept() #ip[0]ip地址 ip[1]端口号
self.users[ip[1]] = client
print(f'欢迎{ip[1]}加入聊天室')
thread1 = threading.Thread(target=self.msg, args=(client,))
thread1.start()
if __name__ == '__main__':
m = Manager()
m.create_server()
客户端
import datetime
import socket
import threading
class Chatter():
messeage = []
def msg_send(self,client):
while True:
str1 = input(':>')
client.send(str1.encode())
#55898@55898@hello
if 'bye'in str1:
with open('client.log','a') as f:
f.write(f'{self.messeage}')
break
def msg_recv(self,client):
while True:
str2 = client.recv(1024).decode()
if str2:
self.messeage.append(f'{datetime.datetime.now()}--{str2}') #缓存到列表里
print(str2)
def create_client(self):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 7007))
#发送的线程
thread1 = threading.Thread(target=self.msg_send,args=(client,))
thread1.start()
#接收的线程
thread2 = threading.Thread(target=self.msg_recv, args=(client,))
thread2.start()
if __name__ == '__main__':
c = Chatter() #创建对象,是为了调用类中的函数
c.create_client()
(二)创建my_web.py,使用python装饰器以及socket实现简易的web静态服务器
1.编写一个TCP服务端程序,支持持续接受浏览器的访问
2.正确获取浏览器发送的HTTP请求报文数据
3.如果请求报文是index的话,返回本地的index.html(文件自定义),如果是资源未找到的话,返回404,如果是baidu的话,支持重定向到baidu的官网
4.读取固定页面数据,把页面数据组装成HTTP响应报文数据发给浏览器
5.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
6.定义日志装饰器,记录每次请求的报文信息以及当前时间到web.log中
import datetime
import socket
from functools import wraps
def my_log(fn): #fn = main
@wraps(fn)
def inner(*args,**kwargs):
bw = fn(*args,**kwargs) #str1是main的返回值
with open('web.log','a') as f:
f.write(f'报文:{bw}---当前时间{datetime.datetime.now()}')
return bw
return inner
@my_log
def main():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 9008))
server.listen(5)
client, ip = server.accept()
bw = client.recv(1024).decode() # 报文
print(bw)
path = bw.split(' ')[1] #地址
print(path)
if path == '/index':
try:
with open('index.html', 'r') as f:
str1 = f.read()
except BaseException as e:
str2 = f'HTTP/1.1 404 not found\nServer:amy\n\n404'
client.send(str2.encode())
print(e)
else:
str2 = f'HTTP/1.1 200 Ok\nServer:amy\n\n{str1}'
client.send(str2.encode())
elif path == '/baidu':
with open('baidu.html', 'r') as f:
str1 = f.read()
str2 = f'HTTP/1.1 307\nServer:amy\n\n{str1}' # 307重定向
client.send(str2.encode())
server.close() #关闭服务器
return bw
if __name__ == '__main__':
main()
(三)创建my_process.py,使用python多进程完成如下需求
具体要求:
1.定义一个进程,随机生成多个数字,存入到队列中
2.定义一个进程,获取生成的数字中,可以构成多少个三角形
3.定义一个进程,获取上面可以构成三角形的3个边的数据,分别计算对应的三角形周长
4.正确保证数据的执行的效果
import multiprocessing
import random
#生成随机3个数,放队列
def get_num(queue1):
for i in range(3):
num = random.randint(1,9)
queue1.put(num)
def check_num(queue1,queue2):
list1 = [] #[1,1,1]
for i in range(3):
list1.append(queue1.get())
#等边
if list1[0]== list1[1] == list1[2]:
print(f'{list1}是等边三角形')
queue2.put([list1]) #[[3,3,3]]
#等腰
elif list1[0]== list1[1] or list1[2]== list1[1] or list1[0]== list1[2]:
#是不是能组成三角形(两边之和大于第三边)
if list1[0]+list1[1] >list1[2] and list1[0]+list1[2] >list1[1] and list1[2]+list1[1] >list1[0]:
queue2.put([list1])
else:
#推导式(三个数字,能有多少种排列的情况) [[],[],[]]
list2 = [[x,y,z] for x in list1 for y in list1 for z in list1 if x+y>z and x+z>y and y+z>x and x!=y and x!=z and y!=z]
queue2.put(list2)
def sum1(queue2):
list3 = queue2.get() #[[1,1,1]] [[2,2,1]] [[],[],[]]
print(f'构成{len(list3)}个三角形')
for i in list3: #i是小列表 ,每个小列表里有三个数字,表示三角形的三条边
print(f'三角形{i},和是{sum(i)}')
if __name__ == '__main__':
queue1 = multiprocessing.Queue()
queue2 = multiprocessing.Queue()
pro1 = multiprocessing.Process(target=get_num,args=(queue1,))
pro1.start()
pro1.join()
pro2 = multiprocessing.Process(target=check_num, args=(queue1,queue2))
pro2.start()
pro2.join()
pro3 = multiprocessing.Process(target=sum1, args=(queue2,))
pro3.start()
pro3.join()
(四)创建my_test.py,完成以下推导式
old_student_score_info={"Jack":{"chinese":87,"math":92,"english":78},
"Tom":{"chinese":92,"math":100,"english":89}}
# 1.从上述包含所有学生成绩信息的字典中,找出数学考满分的同学
dict1 = {k:v for k,v in old_student_score_info.items() if v.get('math') == 100}
print(dict1)
# 2.提取上述图片中每个同学的姓名以及总成绩作为字典,将所有同学的信息存入到列表中
dict1 = {k:sum(v.values()) for k,v in old_student_score_info.items() }
print(dict1)
# 3.生成器推导式生成1-10000直接所有偶数的平方
list43 = (i**2 for i in range(1,10001) if i %2 == 0)
print(list43)
# 4.使用推导式生成如下数据[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
list4 =[(x,y) for x in range(2) for y in range(3)]
print(list4)
# 5.使用嵌套推导式生成九九乘法表
list5 = [f'{x}*{y}={x*y}' for x in range(1,10) for y in range(1,10) if x<=y]
print(list5)