公司动态

Python 语法基础 线程 进程 协程

📅 2026/7/17 20:00:08
Python 语法基础 线程 进程 协程
文章目录一 线程1创建线程2阻塞线程3互斥锁二 线程1常用成员2启动一个进程3 进程的名字4 进程的编号5 启动进程时传参6 子进程存活监测与阻塞7 进程之间的通信7.1队列7.2 进程使用队列跨进程通信三 协程1 定义2 Greenlet2.1安装2.2 使用3 Gevent3.1安装与卸载3.2 常用函数3.3 Monkey 补丁一 线程1创建线程fromthreadingimportThread#导入线程模块importtime#导入时间模块li[]#写入数据defwdata():foriinrange(5):li.append(i)time.sleep(1)print(写入的数据是,li)#读取数据defrdata():print(读取的数据是,li)if__name____main__:#创建子线程t1Thread(targetwdata)t2Thread(targetrdata)#开启子线程t1.start()t2.start()2阻塞线程if__name____main__:#创建子线程t1Thread(targetfun1)t2Thread(targetfun2)#开启子线程t1.start()t1.join()#阻塞主线程直到t1完成t2.start()t2.join()#阻塞主线程直到t2完成3互斥锁当一个锁执行时另一个线程也要使用同一个锁将会等待锁执行完成加锁后必须解锁lockLock()#声明锁 必须是公共变量lock.acquire()#加锁#代码块lock.release()#解锁fromthreadingimportThread,Lock#导入锁importtime a0b2000000lockLock()#声明锁#写入数据deffuna():lock.acquire()#加锁foriinrange(b):globala a1print(方法1a的值,a)lock.release()#解锁#读取数据deffunb():lock.acquire()foriinrange(b):globala a1print(方法2a的值,a)lock.release()if__name____main__:#创建子线程t1Thread(targetfuna)t2Thread(targetfunb)#开启子线程t1.start()t2.start()二 线程1常用成员py提供了Process类代表进程对象Process类构造参数target:执行的任务名称即子进程要执行的任务args 用元组形式传参kwargs 用字典形式传参方法start() 开启子进程isAlive() 子进程是否还活着join() 主进程等待子进程执行结束阻塞属性name 进程的名字 默认Process-N N是从递增的数字pid 进程号2启动一个进程frommultiprocessingimportProcess#导入模块defsing():print(sing)defdance():print(dance)if__name____main__:#创建子进程p1Process(targetsing)#定义进程p2Process(targetdance)p1.start()#开启进程 打印singp2.start()#dance 打印danceprint(p1,p1.name)#p1 Process-1 比sing和dance的打印先执行print(p2,p2.name)#p2 Process-2 比sing和dance的打印先执行3 进程的名字默认名字是 Process-Np1Process(targetsing)#分配默认名字p1.start()#开启进程 打印singprint(p1,p1.name)#p1 Process-1 比sing的打印先执行定义自定义名字p1Process(targetsing,name我喜欢唱歌)#创建时自定义名字p1.start()#开启进程 打印singprint(p1,p1.name)#p1 我喜欢唱歌 比sing的打印先执行#也可以用对象改p1.name我的名字4 进程的编号获取子进程编号p1Process(targetsing)p1.start()print(p1,p1.pid)#p1 44956获取当前进程和父进程的编号frommultiprocessingimportProcessimportos#导入os模块来获取当前的进程号defsing():print(sing的pid,os.getpid())print(sing的父进程pid,os.getppid())if__name____main__:p1Process(targetsing)p1.start()print(python程序的Pid,os.getpid())输出结果5 启动进程时传参frommultiprocessingimportProcessdefeat(name):print(eat,name)if__name____main__:pProcess(targeteat,args(xiaoming,))#注意单参数元组必须加逗号p.start()#eat xiaoming6 子进程存活监测与阻塞frommultiprocessingimportProcessdefeat(name):print(eat,name)if__name____main__:pProcess(targeteat,args(xiaoming,))p.start()print(p.is_alive())#永远是存活因为这里先执行子进程会稍后执行frommultiprocessingimportProcessdefeat(name):print(eat,name)if__name____main__:pProcess(targeteat,args(xiaoming,))p.start()p.join()#使用join主进程会等子进程执行完毕再执行print(p.is_alive())#False 结果永远是false7 进程之间的通信和线程不同进程之间无法共享全局变量7.1队列常用方法put()添加 先入先出如果已经满了还加程序会阻塞永远卡死get()取出empty()是否为空full()是否已经满了size()当前还有多少数据没取fromqueueimportQueue#引入模块qQueue(3)#指定队列长度空或者负值代表没有上限q.put(1)#加入一条数据q.put(第二条数据)q.put(第三条数据)print(q.get())#1 取出消息后第一条会移除print(q.get())#第二条数据print(q.empty())#False7.2 进程使用队列跨进程通信必须使用进程模块提供的Queue类才能跨进程通信普通的Queue类无法跨进程frommultiprocessingimportProcess,Queue正常情况下进程之间不会共享任何数据frommultiprocessingimportProcess,Queue li[]defwData():globalliforiinrange(5):li.append(i)print(写入,li)defrData():globalliprint(读取,li)if__name____main__:p1Process(targetwData)p2Process(targetrData)p1.start()#写入 [0, 1, 2, 3, 4]p2.start()#读取 []使用Queue可以跨进程传递数据frommultiprocessingimportProcess,QueuedefwData(q):foriinrange(5):q.put(i)print(写入,i)defrData(q):whileTrue:ifq.empty():breakelse:print(读取,q.get())if__name____main__:qQueue()#注意队列必须声明在这个if下不能放在最外层p1Process(targetwData,args(q,))p2Process(targetrData,args(q,))p1.start()#写入0 写入1 写入2 写入3 写入4p1.join()p2.start()#读取0 读取1 读取2 读取3 读取4三 协程1 定义生成器就是协程defmyCoroutine():#一个普通方法带yield自动识别为协程yieldayieldbyieldcgmyCoroutine()#协程对象print(next(g))#a 使用next执行下一个yieldprint(next(g))#bprint(next(g))#c常用于IO操作 如文件读写 网络请求2 Greenlet第三方模块封装了协程可以手动切换正在执行的任务2.1安装注意如果使用pycharm编辑会自动给项目创建一个虚拟环境如果使用windows的cmd会导致安装环境不一致所以要用pycharm的控制台安装命令pip install greenlet 或 python-m pip install greenlet卸载pip uninstall greenlet查看安装路径pip show greenlet2.2 使用基础fromgreenletimportgreenlet#引入模块#这是两个普通的方法并非生成器defsing():print(在唱歌)print(唱完了)defdance():print(在跳舞)print(跳完了)if__name____main__:g1greenlet(sing)g2greenlet(dance)g1.switch()#在唱歌 唱完了 只有见到switch才会执行g2.switch()#在跳舞 跳完了任务间切换fromgreenletimportgreenlet#引入模块#这是两个普通的方法并非生成器defsing():print(在唱歌)g2.switch()#在这里将任务切换到别的方法print(唱完了)defdance():print(在跳舞)print(跳完了)if__name____main__:g1greenlet(sing)g2greenlet(dance)g1.switch()#在唱歌 在跳舞 跳完了 执行sing的方法遇到g2.switch()切换到dance执行完danceg1.switch()#唱完了 #然后继续执行剩下的sing3 Gevent和greenlet类似但是他遇到IO操作时会自动切换程序gevent基于greenlet3.1安装与卸载注意如果使用pycharm编辑会自动给项目创建一个虚拟环境如果使用windows的cmd会导致安装环境不一致所以要用pycharm的控制台安装命令python-m pip install gevent3.2 常用函数gevent.spawn(函数名)创建协程对象 gevent.sleep()协程等待类似time.sleepgevent中必须用geven.sleep gevent.join()阻塞等待某个协程执行结束 gevent.joinall()等待所有协程对象都执行结束再退出参数是一个协程对象列表使用实例1 这里没有任何耗时操作只是为了辅助理解调度池importgeventdefsing():print(在唱歌)print(唱完了)defdance():print(在跳舞)print(跳完了)if__name____main__:#创建协程对象 将协程对象自动放入调度池但不会执行g1gevent.spawn(sing)g2gevent.spawn(dance)g2.join()#等待g2执行结束 join的作用是阻塞主线程并等待协程执行完毕 协程会按加入调度池的顺序依次执行 打印结果为 在唱歌 唱完了 在跳舞 跳完了使用实例2importgeventdefsing():print(在唱歌)gevent.sleep(1)#注意不能用time.sleepprint(唱完了)defdance():print(在跳舞)gevent.sleep(3)print(跳完了)if__name____main__:#创建协程对象 将协程对象自动放入调度池但不会执行g1gevent.spawn(sing)g2gevent.spawn(dance)g2.join()#打印结果 在唱歌 在跳舞 唱完了 没有跳完了 因为程序先执行g1,遇到sleep切换到g2g1g2的睡眠同步计时但是g1只睡1秒g2来不及执行此时程序已经退出 如果想让g2完整执行需要加上g2.join()使用实例 3 joinall的使用等所有协程执行完importgeventdefsing():print(在唱歌)gevent.sleep(1)#注意不能用time.sleepprint(唱完了)defdance():print(在跳舞)gevent.sleep(3)print(跳完了)if__name____main__:#创建协程对象 将协程对象自动放入调度池但不会执行g1gevent.spawn(sing)g2gevent.spawn(dance)gevent.joinall([g1,g2])#打印结果 在唱歌 在跳舞 一秒后唱完了 2秒后跳完了使用实例 4 传参defsing(name):print(f{name}在唱歌)gevent.sleep(1)#注意不能用time.sleepprint(唱完了)g1gevent.spawn(sing,我的名字)3.3 Monkey 补丁在模块运行时可以将原本的time.sleep 替换为gevent.sleepfromgeventimportmokey monkey.patch_all()#必须放在前边 运行时会自动把time.sleep替换为gevent.sleepdefsing(name):print(f{name}在唱歌)time.sleep(1)print(唱完了)