num = [int(i) for i in inputs.split()]
# input().split()读一行以空格分开的元素,然后用int()转为整数
#input是字符串 有很多个数的
#用户类
class User:
def __init__(self,first_name,last_name):
self.first_name = first_name
self.last_name = last_name
def describe_user(self):
print(f"当前用户的firstname是{self.first_name},lastname是{self.last_name}")
user1 = User(input("请输入firstname"),input('请输入lastname')) #函数调用时还可以直接用input
user1.describe_user()
在一个类中调用另一个类
class Restaurant: #类名首字母大写
def __init__(self,restaurant_name,cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_served = 0 #就餐人数设置为0
def people_num(self):
print(f"当前已经有{self.number_served}个人在这里吃饭过")
def set_number_served(self,number):
'''修改就餐人数'''
self.number_served = number
self.people_num() #在一个方法中调用另一个方法要用self.方法名()
子类继承父类的属性
class ElectricCar(Car):
def __int__(self,make,model,year):
"""初始化父类的属性"""
super().__init__(make,model,year)
初始化为空字符串,在后面的时候判断是否为空(但不是None),实现该参数的可选性
def get_formatted_place(City,Country,population=''):
if population:
formatted_place = f"{City} {Country}-{population}"
else:
formatted_name = f"{City} {Country}"
return formatted_name
import threading
import time
def loop():
'''新的线程执行的代码'''
n = 0
while n < 5:
print(n)
now_thread = threading.current_thread() # current_thread 用于调用当前正在运行的线程名称
print(f"当前正在运行的线程名称:{now_thread}")
time.sleep(1) #休眠1s
n += 1
def use_thread():
""" 使用线程来实现 """
#创建实例对象
t = threading.Thread(target=loop,name='loop_thread') #目标函数是loop()函数,线程运行的是loop()函数
#启动线程
t.start()
#挂起线程
t.join()
if __name__ == '__main__':
now_thread = threading.current_thread() #current_thread 用于调用当前正在运行的线程名称
print(f"当前正在运行的线程名称:{now_thread}")
use_thread()
import threading
import time
class LoopThread(threading.Thread): #继承自threading.Thread的类
n = 0
def run(self): #重写run方法
while self.n < 5:
now_thread = threading.current_thread()
print(f"当前正在运行的线程名称:{now_thread}")
time.sleep(1)
self.n += 1
if __name__ == '__main__':
t = LoopThread(name = 'LoopThread')
now_thread = threading.current_thread()
print(f"当前正在运行的线程名称:{now_thread}")
t.start() #启动进程
t.join() #挂起进程
import threading,time
#银行存款为balance
balance = 0
def change(n):
#现存后取,结果应该为0
global balance #在函数内部调用全局变量,需定义 global 变量名
balance += n
balance -= n
print(f">>>>>>>>>>{n,balance}")
def run_thread(n):
for i in range(10000):
change(n) #线程中调用函数
if __name__ == '__main__':
t1 = threading.Thread(target=run_thread, args=(5,)) # args: 以元组的方式给任务传入参数
#换句话说,线程t1将调用函数run_thread(5)来执行任务,将数字5作为参数传递给该函数。
t2 = threading.Thread(target=run_thread, args=(8,)) # args: 以元组的方式给任务传入参数
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
#银行存款为balance
balance = 0
def change(n):
global balance
now_thread = threading.current_thread()
print(f"当前正在运行的线程名称:{now_thread}")
balance += n
now_thread = threading.current_thread()
print(f"当前正在运行的线程名称:{now_thread}")
balance -= n
print(f"当前存取金额:{n},当前钱数{balance}")
class ChangeBalanceThread(threading.Thread):
"""改变银行余额的线程"""
def __init__(self,num,*args,**kwargs): #num表示存入银行的钱数 *args用于收集任意数量的位置参数, **kwargs用于收集任意数量的关键字参数
super().__init__(*args,**kwargs)
self.num = num
def run(self):
for i in range(10000):
change(self.num)
if __name__ =='__main__':
now_thread = threading.current_thread()
print(f"当前正在运行的线程名称:{now_thread}")
t1 = ChangeBalanceThread(5) #线程1
t2 = ChangeBalanceThread(8) #线程2
t1.start() #启动线程
t2.start() #启动线程
t1.join() #挂起线程
t2.join() #挂起线程
线程的库是threading
引入time库是为了休眠一会儿
线程中的锁有threading.Loc() threading.RLock() threading.
#代码是 多线程并发问题 代码的改进
import threading,time
#银行存款为balance
balance = 0
#定义锁
my_lock = threading.Lock()
#RLock锁
# my_lock = threading.RLock()
def change(n):
#现存后取,结果应该为0
#方法一
# try:
# my_lock.acquire() #获取锁,即上锁
# global balance #在函数内部调用全局变量,需定义 global 变量名
# balance += n
# balance -= n
# print(f">>>>>>>>>>{n,balance}")
# finally:
# my_lock.release() #释放锁
#方法二
with my_lock:
global balance
balance += n
balance -= n
print(f">>>>>>>{n,balance}")
def run_thread(n):
for i in range(10000):
change(n) #线程中调用函数
if __name__ == '__main__':
t1 = threading.Thread(target=run_thread, args=(5,)) # args: 以元组的方式给任务传入参数
t2 = threading.Thread(target=run_thread, args=(8,)) # args: 以元组的方式给任务传入参数
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
import time
import threading
from concurrent.futures import ThreadPoolExecutor
from multiprocessing.dummy import Pool #进程中的线程池
def run(n):
""" 线程要做的事情 """
time.sleep(2)
print(threading.current_thread().name, n)
def main():
""" 使用传统的方法来做任务 """
t1 = time.time() #获取当前的时间
for n in range(5):
run(n)
print(time.time() - t1) #输出运行的时间
def main_use_thread():
""" 使用线程优化任务 """
# 假设资源有限,最多只能跑10个线程:
t1 = time.time() #获取当前时间
ls = []
for count in range(10): #跑10次,一次2s,一次10个线程并发执行。
for i in range(10): #创建10个线程,并发执行
t = threading.Thread(target=run,args=(i,))
ls.append(t)
t.start()
for l in ls: #10个线程执行完之后,全部阻塞
l.join()
print(time.time() - t1)
def main_use_pool():
""" 使用线程池来优化 """
t1 = time.time()
n_list = range(100)
pool = Pool(10) #创建了一个具有10个线程的线程池
pool.map(run,n_list) #n_list中的每个元素作为run的参数 映射关系
pool.close() #关闭线程池
pool.join() #等待所有任务执行完成后阻塞
print(time.time() - t1)
#用另一种线程池来实现
def main_use_executor():
""" 使用ThreadPoolExecutor """
t1 = time.time()
n_list = range(100)
with ThreadPoolExecutor(max_workers=10) as executor:
executor.map(run,n_list)
print(time.time() - t1)
if __name__ == '__main__':
#main()
#main_use_thread()
#main_use_pool()
main_use_executor()
使用multiprocessing实现多进程代码
使用multiprocessing.Process创建进程
start()启动进程
join()挂起进程
import os os.getpid()获取进程id
import os #用于得到进程的pid
import time
from multiprocessing import Process
def do_sth(name):
"""
:param name: str 表示进程的名称
"""
print(f"进程的名称为{name},进程的id为{os.getpid()}") #os.getpid()可用于获取当前进程的pid
time.sleep(2) #休眠2s
print("进程要做的事")
if __name__ == '__main__':
# 目标函数是do_sth 参数是一个元组,传入进程名称
#下面两种方法都可以建立进程
# p = Process(target=do_sth('My Process yellow'))
p = Process(target=do_sth,args=('my process yellow',))
#启动进程
p.start()
#挂起进程
p.join()
import os
import time
from multiprocessing import Process
def do_sth(name):
"""
进程要做的事情
:param name: str 进程的名称
"""
print(f"进程的名称{name},进程的id:{os.getpid()}")
time.sleep(2)
print("进程要做的事情")
class MyProcess(Process): #继承Process
def __init__(self,name,*args,**kwargs):
# #将进程的属性my_name赋值为name。不赋值为name是因为其父类Process中也有属性叫name,后面再继承父类会覆盖前面的赋值
self.my_name = name
#继承父类
super().__init__(*args,**kwargs)
def run(self): #重写run函数
print(f"当前进程的名称{self.my_name},"
f"进程的id:{os.getpid()}")
time.sleep(2) #休眠2s
print("进程要做的事")
if __name__ == '__main__':
#创建一个使用继承类实现进程的方法
p = MyProcess('my process using class')
#运行进程
p.start()
#挂起进程
p.join()
通过使用multiprocess中的Queue实现进程之间的通信。
获取当前进程名称的方法:1.如果是写一个函数,直接用Process(target =,args = )则需要调用multiprocessing中的current_process.name
2.如果是重写multiprocessing中的Process方法,则直接调用multiprocessing中的self.name即为当前进程的名称
import multiprocessing
import time
from multiprocessing import Process,Queue
from random import randint
class WriteProcess(Process):
""" 实现写进程 """
def __init__(self,q,*args,**kwargs):
self.q = q #q是 队列
super().__init__(*args,**kwargs)
def run(self):
"""实现进程的业务逻辑"""
#要写的内容
ls = ['第一行内容',
'第二行内容',
'第三行内容']
for line in ls:
print(f"当前在写入:{line}")
self.q.put(line)
#如何获取当前进程对象的名称?
#1.如果是写一个函数,直接用Process(target =,args = )则需要调用multiprocessing中的current_process.name()
#2.如果是重写multiprocessing中的Process方法,则直接调用multiprocessing中的self.name即为当前进程的名称
print(f"当前进程的名称{self.name}")
#每写入一次,休息1-6s
time.sleep(randint(1,6))
class ReadProcess(Process):
""" 实现读进程 """
def __init__(self,q,*args,**kwargs):
self.q = q
super().__init__(*args,**kwargs)
def run(self):
# 用死循环来实现读进程
while True:
content = self.q.get()
print(f"读取到的内容是{content}")
# 如何获取当前进程对象的名称?
# 1.如果是写一个函数,直接用Process(target =,args = )则需要调用multiprocessing中的current_process.name
# 2.如果是重写multiprocessing中的Process方法,则直接调用multiprocessing中的self.name即为当前进程的名称
print(f"当前进程的名称{multiprocessing.current_process().name}")
if __name__ == '__main__':
#创建队列对象
q = Queue()
#写进程
writeprocess = WriteProcess(q)
#读进程
readprocess = ReadProcess(q) #读写进程采用同一个队列对象
writeprocess.start()
readprocess.start()
writeprocess.join()
#如果采用读进程阻塞,而读进程为死循环,则读进程无法结束。所以不应该阻塞读进程,应该直接终止terminate读进程
# readprocess.join()
readprocess.terminate() #终止读进程,此时程序可直接结束。
锁有Lock RLock condition。
Lock只能锁一次,RLock和Lock的唯一不同是RLock可以锁定两次
笔记:
#以追加a+的方式往文件中写 打开文件的编码方式为utf-8
with open(self.file_name,'a+',encoding='utf-8') as f:
import random
import time
from multiprocessing import Process, Lock
class WriteProcess(Process):
""" 往文件中写入内容 """
def __init__(self,file_name,num,lock,*args,**kwargs):
self.file_name = file_name
self.num = num
#锁对象
self.lock = lock
super().__init__(*args,**kwargs) #*args, **kwargs 叫魔法参数
def run(self):
# 往文件中写内容
with self.lock: #必须是self.lock 锁是类的对象。要用self.
for i in range(5):
content = f"当前进程名称是{self.name},进程pid是{self.pid}, 数字是{self.num}"
with open(self.file_name,'a+',encoding='utf-8') as f: #以追加a+的方式往文件中写 打开文件的编码方式为utf-8
f.write(content+'\n') #写入内容
#time.sleep(random.randint(1,5)) #随机休息1-5秒钟
if __name__ == '__main__':
file_name = 'name.txt'
#锁的对象
lock = Lock()
for x in range(5):
p = WriteProcess(file_name,x,lock)
p.start()
import multiprocessing
from multiprocessing import pool
def run(file_name,num):
"""往文件中写入数据"""
with open(file_name,'a+',encoding='utf-8') as f:
now_process = multiprocessing.current_process()
content = f"当前进程的名称是{now_process.name}," \
f"进程的id是{now_process.pid}," \
f"要写入的字符是{num}"
f.write(content+'\n')
return 'ok'
if __name__ =='__main__':
#创建一个容量为2的进程池
pool = multiprocessing.Pool(2)
file_name = 'tes_using_pool.txt'
for i in range(20):
#apply方法是同步方法
# result = pool.apply(run,args=(file_name,i)) #等价与run(file_name,i)
#使用异步方法
result = pool.apply_async(run,args=(file_name,i))
#使用get方法可以得到写入数据返回的结果。
print(f"{i}----{result.get()}")
#关闭池子
pool.close()
pool.join()
协程的实现的步骤:
- 定义协程函数
async def
- 创建事件的循环队列
loop = asyncio.get_event_loop()
- 注册任务,把任务加入到事件的循环队列中
task = loop.create_task(coroutine)
- 等待协程的执行结束
loop.run_until_complete(task)
asyncio模块
asyncio.get_event_loop()
获取事件循环队列
loop.run_until_complete(task)
注册任务到队列
在事件循环中调度其执行前,写成对象不执行任何操作。
asyncio模块用于事件循环
import asyncio
import time
async def do_sth(x):
"""定义协程函数"""
print(f"等待中:{x}")
#等待5s再往后执行
await asyncio.sleep(x)
#判断是否为协程函数
print(asyncio.iscoroutinefunction(do_sth))
coroutine = do_sth(5)
#事件的循环队列
loop = asyncio.get_event_loop()
#注册任务,把任务加到事件循环队列中
task = loop.create_task(coroutine)
print(task)
#等待协程任务执行结束
loop.run_until_complete(task)
print(task)
True
<Task pending name='Task-1' coro=<do_sth() running at D:\python\多线程和进程\协程的实现.py:5>>
等待中:5
<Task finished name='Task-1' coro=<do_sth() done, defined at D:\python\多线程和进程\协程的实现.py:5> result=None>
要得到一个协程函数的运算结果使用await方法
asyncio 异步IO
import asyncio
async def compute(x,y):
print(f"Compute {x} + {y}")
await asyncio.sleep(1.0)
return x + y
async def print_sum(x,y):
result = await compute(x,y) #使用await才能拿到另一个协程的运算结果。
print(f"{x} + {y} = {result}")
#拿到事件循环
loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1,2))
loop.close()
import asyncio
#使用队列q实现协程函数之间的通信
#往队列中添加数据
async def add(q,name):
#使用for循环往队列中添加数据
for i in range(5):
content = f"当前协程名称{name},写入队列的内容是{i}"
# asyncio中的队列添加时返回的时写成对象,因此必须在前面加await
#q.put(i)
await asyncio.sleep(2) # 休息2s
await q.put(i) #返回的是协程的对象,因此必须await来获取结果。
print(f"{content},当前队列中的元素个数为{q.qsize()}")
async def reduce(q,name):
"""
:param q:
从队列中删除对象
"""
for i in range(10):
content = f"当前协程的名称是{name},要删除的内容是{i}"
result = await q.get() #获取协程对象,使用await等待协程完成
print(f"{content},当前元素剩余为{q.qsize()}")
if __name__ =='__main__':
#准备一个队列
q = asyncio.Queue(maxsize=5)
a1 = add(q,'a1')
a2 = add(q,'a2')
r1 = reduce(q,'r1')
#添加到事件队列
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(a1,a2,r1)) #将多个协程同时添加到事件队列中
loop.close()