回顾之前易忘记的知识

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 吃 %s33[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 生产了 %s33[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("出错了")

  

原文地址:https://www.cnblogs.com/liuwei0824/p/10838774.html