156 lines
6.7 KiB
Python
156 lines
6.7 KiB
Python
# 1.举例说什么是IO密集型任务?
|
|||
|
|
print('程序大部分时间不是在做cpu计算,而是等待外部设备的输入和输出 比如就是传输数据,cpu只用来打开,其他时间就是等待 ')
|
||
|
|
|
||
|
|
print(' ')
|
||
|
|
print(' ')
|
||
|
|
print(' ')
|
||
|
|
print(' ')
|
||
|
|
# 2.什么是多进程、多线程?以及它们之间的区别是什么?举例说说自己的理解
|
||
|
|
print(' 多进程是同一个程序,可以有多个进程,每个进程相互独立,有自己的内存, ')
|
||
|
|
print(' 多线程是在一个进程内部,开启多个线程,线程之间互相共享资源,如果有一个崩溃,全部都会受影响 ')
|
||
|
|
print(' 区别就是,多线程资源共享,开销小,效率高,通讯很快。但是会有崩溃问题和竞争问题 ')
|
||
|
|
print(' 多进程互相独立,开销大,有自己的内存,适合cpu密集使用。 ')
|
||
|
|
# 3.什么是同步编程、异步编程?举例说说自己的理解
|
||
|
|
print(' 同步编程:代码从上到下执行,执行过程中遇到耗时操作或者(io/等待)会原地堵塞,需要等到前面的任务完成才能执行下一段代码 ')
|
||
|
|
print(' 异步编码:基于asyncio时间调度,执行过程中遇到耗时操作或者(io/等待),会主动暂停和交出cpu控制权,'
|
||
|
|
'去执行其他的就绪任务,等到等待完后再回来继续执行代码 ')
|
||
|
|
print(' 同步编程适合计算密集型任务,直接一步到位。异步编码适合多io密集型,在等待时候跳过执行其他就绪任务 ')
|
||
|
|
# 4.单核单线程能不能执行多个进程任务?为什么?
|
||
|
|
print(' 可以,因为进程可以通过并发的方法,错开时间可以在极短的时间从里快速切换多个进程,暂停当前任务,执行下个任务,间隔时间极短。 ')
|
||
|
|
|
||
|
|
# 5.什么是python的GIL锁?为什么python会这么设计GIL锁?
|
||
|
|
print(' GIL锁是CPython中的全局解释器锁 ')
|
||
|
|
print(' 他保证同一个时刻只有一个线程执行phython程序,'
|
||
|
|
'从而简化了内存管理,避免了多线程同时进行导致的数据错乱的问题。但是限制了多线程在cpu密集型任务中的并行能力 ')
|
||
|
|
|
||
|
|
# 6.将课上的多线程案例、多进程案例、同步编程案例、异步编程案例敲到作业上来,加深自己的理解!
|
||
|
|
print(' 多进程案例 ')
|
||
|
|
import multiprocessing
|
||
|
|
import time
|
||
|
|
def task(name,t):
|
||
|
|
print(f'进程{name}启动,耗时{t}s')
|
||
|
|
time.sleep(t)
|
||
|
|
print(f'进程{name}完成')
|
||
|
|
if __name__=='__main__':
|
||
|
|
start=time.time()
|
||
|
|
p1 = multiprocessing.Process(target=task, args=("A", 2))
|
||
|
|
p2 = multiprocessing.Process(target=task, args=("B", 2))
|
||
|
|
p1.start()
|
||
|
|
p2.start()
|
||
|
|
p1.join()
|
||
|
|
p2.join()
|
||
|
|
end_time = time.time()
|
||
|
|
print(f"总耗时:{end_time - start:.1f}s")
|
||
|
|
|
||
|
|
print('多线程案例')
|
||
|
|
import threading, time
|
||
|
|
|
||
|
|
def coding(name, count):
|
||
|
|
for i in range(count):
|
||
|
|
print(f'{name}正在敲第{i+1}行代码')
|
||
|
|
time.sleep(0.1)
|
||
|
|
|
||
|
|
def music(name, count):
|
||
|
|
for i in range(count):
|
||
|
|
print(f'{name}正在听第{i+1}首音乐...')
|
||
|
|
time.sleep(0.1)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
start = time.time()
|
||
|
|
p1 = threading.Thread(target=coding, args=('zs', 30))
|
||
|
|
p2 = threading.Thread(target=music, args=('ls', 30))
|
||
|
|
p1.start()
|
||
|
|
p2.start()
|
||
|
|
|
||
|
|
p1.join()
|
||
|
|
p2.join()
|
||
|
|
end = time.time()
|
||
|
|
print(f'多线程执行耗:{end - start}s')
|
||
|
|
|
||
|
|
|
||
|
|
print('同步')
|
||
|
|
import time
|
||
|
|
def task1():
|
||
|
|
print(f'{time.time():.2f}')
|
||
|
|
time.sleep(1)
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
return "task1_result"
|
||
|
|
|
||
|
|
def task2():
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
time.sleep(2)
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
return "task2_result"
|
||
|
|
|
||
|
|
def main():
|
||
|
|
start = time.time()
|
||
|
|
res1 = task1()
|
||
|
|
res2 = task2()
|
||
|
|
print("结果:", res1, res2)
|
||
|
|
print(f"耗时:{time.time() - start}秒")
|
||
|
|
main()
|
||
|
|
|
||
|
|
print('异步')
|
||
|
|
import asyncio
|
||
|
|
import time
|
||
|
|
|
||
|
|
async def task1():
|
||
|
|
print(f"{time.time():.2f}")
|
||
|
|
await asyncio.sleep(1) # 异步休眠,主动交出CPU
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
return "task1_result"
|
||
|
|
|
||
|
|
async def task2():
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
await asyncio.sleep(2)
|
||
|
|
print(f"{time.time():.2f} ")
|
||
|
|
return "task2_result"
|
||
|
|
|
||
|
|
async def main():
|
||
|
|
start = time.time()
|
||
|
|
res1, res2 = await asyncio.gather(task1(), task2())
|
||
|
|
print("最终结果:", res1, res2)
|
||
|
|
print(f"耗时:{time.time() - start}秒")
|
||
|
|
asyncio.run( main() )
|
||
|
|
|
||
|
|
'''
|
||
|
|
7.Python设计编写一个日志模块 log.py ,里面定义一个类,实现企业级别的日志功能调用,需求功能如下:
|
||
|
|
①模块里调用了logging日志模块,定义一个类Log
|
||
|
|
②Log类里定义了初始化方法__init__(),初始化方法需要入两个参数,一个是日志器的名字name,一个是日志等级level,实例属性self.logName用来接收实例化的日志器的名字,需要其他属性时自己定义即可
|
||
|
|
③定义logFile()方法,实例对象调用该方法时,需要入参文件名字fileName,调用该方法就启用日志器信息输出到指定的文件名里,日志的信息格式统一都是"年月日时分秒 - 日志器名字 - 日志等级 - 日志信息",输入的字符集编码写死成utf-8即可
|
||
|
|
④定义logConsol()方法,实例对象调用该方法时,调用该方法就启用日志器信息输出到控制台,日志的信息格式统一都是"年月日时分秒 - 日志器名字 - 日志等级 - 日志信息"
|
||
|
|
⑤最后定义一个message()方法,两个形参,一个形参接收日志级别,一个形参接收日志信息,实例调用该方法时,输出不同的日志级别信息
|
||
|
|
|
||
|
|
在别的文件里调用示例如下:
|
||
|
|
# 【main.py文件】调用
|
||
|
|
from log import Log
|
||
|
|
lg3 = Log('ai大模型','info') # 实例化一个日志器的名字叫做'ai大模型',日志级别是info
|
||
|
|
lg3.logConsol() # 调用方法,定义输出到控制台
|
||
|
|
|
||
|
|
lg3.message('debug','这是debug日志')
|
||
|
|
lg3.message('info','这是info日志')
|
||
|
|
lg3.message('error','这是error日志')
|
||
|
|
|
||
|
|
lg3.logFile('ai0824.log') # 调用方法,输出日志到指定的文件名
|
||
|
|
lg3.message('info','这是info日志......')
|
||
|
|
lg3.message('error','这是error日志......')
|
||
|
|
|
||
|
|
'''
|
||
|
|
import logging
|
||
|
|
|
||
|
|
class Log:
|
||
|
|
def __init__(self, name: str, level: str):
|
||
|
|
self.log_name = name
|
||
|
|
self.logger = logging.getLogger(self.log_name)
|
||
|
|
self.logger.handlers.clear()
|
||
|
|
level_map = {"debug": logging.DEBUG,
|
||
|
|
"info": logging.INFO,
|
||
|
|
"warning": logging.WARNING,
|
||
|
|
"error": logging.ERROR,
|
||
|
|
"critical": logging.CRITICAL }
|
||
|
|
self.logger.setLevel(level_map.get(level.lower(), logging.INFO))
|
||
|
|
|
||
|
|
|
||
|
|
|