1.操作系统的发展历史中产生了多道技术:
多道技术:(多道指的是多道/个程序)
空间上的复用:内存中进入多个程序
PS:内存必须实现物理级别的隔离
时间上的复用:cpu要切换:
1. 一个程序占用cpu的时间过长
2. 一个程序遇到I/O阻塞
产生背景:针对单核,实现并发
2.网络传输五层协议:物理层 - 数据链路层(以太网协议--> head + data) - 网络层(IP -- 路由) - 传输层(TCP, UDP) - 应用层(HTTP)
3.变量的三个特征: id, type, value
4.可变类型是不可hash类型 hash 是什么?
不可变类型是可hash类型
5.集合的元素遵循三个原则:1:每个元素必须是不可变类型 2:没有重复的元素 3:无序
6.为什么py3中字符串是str py2中是bytes类型?
7.文件处理?
8.内置函数?
11. md5 一个文件
import hashlib
md5_obj = hashlib.md5()
import os
filesize = os.path.getsize('filename')
f = open('filename','rb')
while filesize>0:
if filesize > 1024:
content = f.read(1024)
filesize -= 1024
else:
content = f.read(filesize)
filesize -= filesize
md5_obj.update(content)
md5_obj.hexdigest()
12.socket 是什么? 它是网路传输过程中 应用层与传输层中间的一个接口, 它把复杂的TCP,UDP等协议封装在身后, 只留出我们看到的接口,
至于内部是怎么实现的网路连接等等不需要我们知道。
13. TCP 的三次握手 和四次挥手:
握手(我来了你准备好了吗--> 收到,我也准备好了,你来吧 --> 好的)
挥手(我要走了,你准备好了吗 --> 你先等一下我还有东西给你 --> 好了吗 --> 好了 )
14.为何tcp是可靠传输,udp是不可靠传输?
tcp在数据传输时,发送端先把数据发送到自己的缓存中,然后协议控制将缓存中的数据发往对端,对端返回一个ack=1,发送端则清理缓存中的数据,对端返回ack=0,则重新发送数据,所以tcp是可靠的
15.粘包:
1.发送数据时间间隔很短,数据了很小,会合到一起,产生粘包
2.接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
解决办法: 发送端先发送报头的长度 --> 发报头数据 --> 最后发送数据
16.操作系统的两大作用:一是为软件提供简单的接口来操作硬件。二是使多个软件对硬件的需求变得有序化
17.multiprocessing类实现开启子进程 (from multiprocessing import Process)
p=Process()
p.daemon = True # 守护进程,守护进程不可以再有子进程,并且主进程死守护进程就死,要写在p.start()之前
p.join() # 主进程等子进程执行完 之后再结束---> 等的时间就是执行时间最长的子进程执行的时间
p.terminate() # 强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,用该方法需要特别小心这种情况。如果p保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive() # 如果p仍然运行,返回True
p.name # 查看进程的名称
p.pid -->查看进程的pid
p.ppid -->查看进程的父进程pid
主进程不会等待子进程的结束,除非加了join方法
18.共享就存在竞争,----加锁-----队列
19.创建线程模块:from threading import Thread
多线程共享它们进程的资源,线程的创建比创建进程开销小
守护线程: 主线程的非守护线程执行完(主线程执行完毕)——>守护死
20.GIL 锁 与 Lock锁
21.进程池、线程池:from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
进程池 默认个数是CPU个数,而线程池的默认个数是CPU个数的5倍
22.协程
优点:创建时消耗资源更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
缺点:1.协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
gevent 模块实现协程:
from gevent import monkey;monkey.patch_all() #monkey;monkey.patch_all() 可以识别其他的I/O操作
import gevent
import time,threading
def eat(name):
print('%s eat 1' %name)
time.sleep(2)
print('%s eat 2' %name)
return 'eat'
def play(name):
print('%s play 1' %name)
time.sleep(3)
print('%s play 2' %name)
return 'play'
start=time.time()
g1=gevent.spawn(eat,'egon')
g2=gevent.spawn(play,'egon')
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
print('主',(time.time()-start))
print(g1.value)
print(g2.value)
# 结果:
egon eat 1
egon play 1
egon eat 2
egon play 2
主 3.0018091201782227
eat
play
23.select,poll,epoll实现IO多路复用机制 三个模块的区别:
select模块自动监听多个套接字 (谁好了就返回谁)
但是监听的套接字(socket)个数不是无限多的
poll的实现机制和select时非常相似的
epoll模型可以解决套接字个数非常多的情况(因为它的内部检测哪个套接字好了的机制和select不同
(select是遍历每个套接字,看有没有好了的, 而epoll是 如果哪个套接字好了,就自动跑出来)),
但是windows不支持epoll模型
24.数据库的curd基本语句
25.InnoDB 支持事务,支持行级别锁定、 Memory 不支持事务,支持表级别锁定,
MyISAM 不支持事务,支持表级别锁定
26.from multiprocessing import Process,JoinableQueue,Queue
import time,random,os
def consumer(q):
while True:
res=q.get()
if res is None:break #收到结束信号则结束
time.sleep(random.randint(1,3))
print(' 33[45m%s 吃 %s 33[0m' %(os.getpid(),res))
q.task_done() # 向q.join()发送一次信号,证明一个数据已经被取走了
def producer(name,q):
for i in range(2):
time.sleep(random.randint(1,3))
res='%s%s' %(name,i)
q.put(res)
print(' 33[44m%s 生产了 %s 33[0m' %(os.getpid(),res))
# q.join() #q.join除了可以放在主进程里面,也可以放在这里
if __name__ == '__main__':
q=JoinableQueue()
#生产者们:即厨师们
p1=Process(target=producer,args=('包子',q))
p2=Process(target=producer,args=('骨头',q))
p3=Process(target=producer,args=('泔水',q))
#消费者们:即吃货们
c1=Process(target=consumer,args=(q,))
c2=Process(target=consumer,args=(q,))
c1.daemon=True #设置成守护进程
c2.daemon=True
#开始
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
p1.join() #必须保证生产者全部生产完毕,才应该发送结束信号
p2.join()
p3.join()
q.join() #生产者和消费者的进程都完成了
print('主')
#为什么设置消费者为守护进程,因为执行到最后,生产者进程执行完了,主进程也完成了,但是由于消费者
#进程是死循环,并没有结束,设置成守护进程后,主进程结束了,c1和c2也就可以结束了
27. 现有两个元组(('a'),('b')),(('c'),('d')), 请使用python中匿名函数生成列表[{'a':'c'},{'b':'d'}]
28. assert 断言是什么?它的使用场景?
29. logging模块的使用
import logging
def my_logger(filename,file=True,stream = True):
logger = logging.getLogger()
formatter = logging.Formatter(fmt='%(name)s %(asctime)s [%(lineno)d] -- %(message)s',
datefmt='%d/%m/%y %H:%M:%S')
logger.setLevel(logging.DEBUG)
if file:
file_handler = logging.FileHandler(filename,encoding='utf-8')
file_handler.setFormatter(formatter) # 文件流 文件操作符
logger.addHandler(file_handler)
if stream:
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter) #屏幕流 屏幕操作符
logger.addHandler(stream_handler)
return logger
logger = my_logger('logging',file=False)
logger.warning("出错了")