041.Python守护进程,锁信号量和事件

一 守护进程

1.1 基本概念

守护进程

  • 正常情况下,主进程默认等待子进程调用结束之后结束
  • 守护进程在主进程执行代码结束后,自动终止

守护进程语法:

  • 进程对象.daemon = True ,设置该进程是守护进程
  • 守护进程需要在start()方法之前设置
  • 为主进程守护,主进程如果代码执行结束了,该守护进程自动结束.

1.2 基本语法

import os
import time
from multiprocessing import Process
def func():
        print("子进程start")
        print("子进程end")
p = Process(target=func)
p.start()
print ("主进程执行结束")

执行

[[email protected] python]# python3 test.py
主进程执行结束
子进程start
子进程end

使用守护进程

import os
import time
from multiprocessing import Process
def func():
        print("子进程start")
        print("子进程end")
p = Process(target=func)
p.daemon = True
p.start()
print ("主进程执行结束")

执行

[[email protected] python]# python3 test.py
主进程执行结束

主进程执行完之后,子进程不在执行

1.3 多个子进程情况

import os
import time
from multiprocessing import Process
def func1():
        count = 1
        while True:
                print ("*" * count)
                time.sleep(0.5)
                count += 1
def func2():
        print("func2 start")
        time.sleep(3)
        print("func2 end")
p1 = Process(target=func1)
p1.start()
p2 = Process(target=func2)
p2.start()
print ("主进程执行结束")

执行

[[email protected] python]# python3 test.py
主进程执行结束
*
func2 start
**
***
****
*****
******
func2 end
*******
********
*********
**********
***********
************
*************
**************
***************
****************
*****************
******************
*******************
********************
*********************
**********************

第一个进程不能结束,设置一个守护进程

import os
import time
from multiprocessing import Process
def func1():
        count = 1
        while True:
                print ("*" * count)
                time.sleep(0.5)
                count += 1
def func2():
        print("func2 start")
        time.sleep(3)
        print("func2 end")
p1 = Process(target=func1)
p1.daemon = True
p1.start()
p2 = Process(target=func2)
p2.start()
print ("主进程执行结束")

但这种添加还没来得及执行,就被杀掉

执行

[[email protected] python]# python3 test.py
主进程执行结束
func2 start
func2 end

当多个子进程并发执行时,默认主进程等待子进程的

如果标记该子进程是守护进程,当主进程执行完所有代码之后,守护进程立刻终止

主进程代码执行到最后一行,就意味着守护进程终止了,其他非守护进程继续执行,主进程仍然会等待他执行结束,最后主进程在真正的释放结束.

1.4 守护进程用途: 报活功能

import os
import time
from multiprocessing import Process
def alive():
        while True:
                print ("I am the first server,I‘m  OK")
                time.sleep(0.5)
def func():
        print("The first server is used to collect logs")
        time.sleep(5)   #相当于这个进程存活5s
p1 = Process(target=alive)
p1.daemon = True
p1.start()
p2 = Process(target=func)
p2.start()
#模拟func程序结束,或者服务器宕机,停止保活,这是执行主进程,执行完,则子进程不在执行,即停止报活
p2.join()
print (".......")

执行

[[email protected] python]# python3 test.py
I am the first server,I‘m  OK
The first server is used to collect logs
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
I am the first server,I‘m  OK
.......

二 lock锁

语法:
# 创建一把锁
lock = lock()
# 上锁
lock.acquire()
# 解锁
lock.release()

2.1 基本用法

import os
import time
from multiprocessing import Process,Lock
lock = Lock()
lock.acquire()
lock.release()
print (111)

执行

[[email protected]node10 python]# python3 test.py
111

死锁 上锁和解锁之间不匹配,只上锁不解锁就是死锁,会产生阻塞;

import os
import time
from multiprocessing import Process,Lock
lock = Lock()
lock.acquire()
#lock.release()
print (111)

执行就会被阻塞,而且不会打印111,成了一把死锁

2.2 模拟一个抢票机制

假设只有一张票

[[email protected] python]# vim ticket

{"count": 1}

抢票方法

import os
import time,json
from multiprocessing import Process,Lock
def wr_info(sign,dic=None):
        if sign == "r":
                with open("ticket",mode="r",encoding="utf-8") as fp:
                        dic = json.load(fp)
                return dic
        elif sign == "w":
                with open("ticket",mode="w",encoding="utf-8") as fp:
                        json.dump(dic,fp)

#抢票方法
def get_ticket(person):
        dic = wr_info("r")
        time.sleep(0.11)
        if dic["count"] > 0:
                print("%s抢到票"%(person))
                dic["count"] -=1
#               更新数据库
                wr_info("w",dic)
        else:
                print ("%s没有买到票"%(person))

#用ticket来仅从统一调用
def ticket(person):
        #查询票数
        dic = wr_info("r")
        print ("%s查询余票:%s"%(person,dic[‘count‘]))
        get_ticket(person)

for i in range(10):
        p = Process(target = ticket,args=( "person%s" %(i), ))
        p.start()

执行

[[email protected] python]# python3 test.py
person0查询余票:1
person1查询余票:1
person2查询余票:1
person3查询余票:1
person4查询余票:1
person5查询余票:1
person6查询余票:1
person7查询余票:1
person8查询余票:1
person9查询余票:1
person3抢到票
person0抢到票
person4抢到票
person5抢到票
person1抢到票
person7抢到票
person2抢到票
person6抢到票
person8抢到票
person9抢到票

发现所有人都抢到票了

2.3 使用锁机制

在主进程创建一把锁,在抢票处上锁,然后再抢完解锁,如下操作

import os
import time,json
from multiprocessing import Process,Lock
def wr_info(sign,dic=None):
        if sign == "r":
                with open("ticket",mode="r",encoding="utf-8") as fp:
                        dic = json.load(fp)
                return dic
        elif sign == "w":
                with open("ticket",mode="w",encoding="utf-8") as fp:
                        json.dump(dic,fp)

#抢票方法
def get_ticket(person):
        dic = wr_info("r")
        time.sleep(0.11)
        if dic["count"] > 0:
                print("%s抢到票"%(person))
                dic["count"] -=1
#               更新数据库
                wr_info("w",dic)
        else:
                print ("%s没有买到票"%(person))

#用ticket来仅从统一调用
#这里需要把lock传进来
def ticket(person,lock):
        #查询票数
        dic = wr_info("r")
        print ("%s查询余票:%s"%(person,dic[‘count‘]))
        lock.acquire()
        get_ticket(person)
        lock.release()
lock = Lock()
for i in range(10):
        p = Process(target = ticket,args=( "person%s" %(i), ))
        p.start()

执行

主进程在执行ticket的子进程时,多一个参数

import os
import time,json
from multiprocessing import Process,Lock
def wr_info(sign,dic=None):
        if sign == "r":
                with open("ticket",mode="r",encoding="utf-8") as fp:
                        dic = json.load(fp)
                return dic
        elif sign == "w":
                with open("ticket",mode="w",encoding="utf-8") as fp:
                        json.dump(dic,fp)

#抢票方法
def get_ticket(person):
        dic = wr_info("r")
        time.sleep(0.11)
        if dic["count"] > 0:
                print("%s抢到票"%(person))
                dic["count"] -=1
#               更新数据库
                wr_info("w",dic)
        else:
                print ("%s没有买到票"%(person))

#用ticket来仅从统一调用
#这里需要把lock传进来
def ticket(person,lock):
        #查询票数
        dic = wr_info("r")
        print ("%s查询余票:%s"%(person,dic[‘count‘]))
        lock.acquire()
        get_ticket(person)
        lock.acquire()
lock = Lock()
for i in range(10):
        p = Process(target = ticket,args=( "person%s" %(i), lock))
        p.start()

执行

[[email protected] python]# python3 test.py
person0查询余票:1
person1查询余票:1
person2查询余票:1
person3查询余票:1
person4查询余票:1
person5查询余票:1
person6查询余票:1
person7查询余票:1
person8查询余票:1
person9查询余票:1
person0抢到票
person1没有买到票
person2没有买到票
person3没有买到票
person4没有买到票
person5没有买到票
person6没有买到票
person7没有买到票
person8没有买到票
person9没有买到票

或者直接加锁

import os
import time,json
from multiprocessing import Process,Lock
def wr_info(sign,dic=None):
        if sign == "r":
                with open("ticket",mode="r",encoding="utf-8") as fp:
                        dic = json.load(fp)
                return dic
        elif sign == "w":
                with open("ticket",mode="w",encoding="utf-8") as fp:
                        json.dump(dic,fp)

#抢票方法
def get_ticket(person):
        dic = wr_info("r")
        time.sleep(0.11)
        if dic["count"] > 0:
                print("%s抢到票"%(person))
                dic["count"] -=1
                #更新数据库
                wr_info("w",dic)
        else:
                print ("%s没有买到票"%(person))

#用ticket来进行统一调用
#这里需要把lock传进来
def ticket(person):
        #查询票数
        dic = wr_info("r")
        print ("%s查询余票:%s"%(person,dic[‘count‘]))
        lock.acquire()
        #开始抢票
        get_ticket(person)
        lock.release()

lock = Lock()
for i in range(10):
        p = Process(target = ticket,args=( "person%s"%(i),))
        p.start()

区分同步和异步

  • 在产生进程对象的时候,进程之间是异步的.上锁之后,进程是同步的
  • 必须等上一个进程执行完毕之后,下一个进行才能执行,这个是同步.

三  信号量

Semaphore 本质上就是锁,只不过可以控制锁的数量

模拟取钱,假设10个人排队取钱

import os
import time,json
from multiprocessing import Process,Lock,Semaphore

def bank(person):
        print ("%s进入柜台取钱"%(person))
        print ("%s取完离开"%(person))

for i in range(10):
        p = Process(target = bank,args=("person%s"%(i),))
        p.start()

执行

[[email protected] python]# python3 test.py
person0进入柜台取钱
person0取完离开
person1进入柜台取钱
person1取完离开
person2进入柜台取钱
person2取完离开
person3进入柜台取钱
person3取完离开
person4进入柜台取钱
person4取完离开
person5进入柜台取钱
person5取完离开
person6进入柜台取钱
person6取完离开
person7进入柜台取钱
person7取完离开
person8进入柜台取钱
person8取完离开
person9进入柜台取钱
person9取完离开

假设4个柜台使用semaphore上四把锁

import os
import time,json
from multiprocessing import Process,Lock,Semaphore

def bank(person):
        sem.acquire()
        time.sleep(5)
        print ("%s进入柜台取钱"%(person))
        print (os.getpid())
        res = os.popen("date").read()
        print(res)
        sem.release()
        print ("%s取完离开"%(person))

sem = Semaphore(4)
for i in range(10):
        p = Process(target = bank,args=("person%s"%(i),))
        p.start()

执行

person0进入柜台取钱
person3进入柜台取钱
4502
4505
Sat Feb 22 21:58:07 EST 2020
Sat Feb 22 21:58:07 EST 2020

person0取完离开
person3取完离开
person1进入柜台取钱
4503
Sat Feb 22 21:58:07 EST 2020

person1取完离开
person2进入柜台取钱
4504
Sat Feb 22 21:58:07 EST 2020

person2取完离开
person5进入柜台取钱
4507
Sat Feb 22 21:58:12 EST 2020

person5取完离开
person6进入柜台取钱
4508
Sat Feb 22 21:58:12 EST 2020

person6取完离开
person7进入柜台取钱
person4进入柜台取钱
4506
4509
Sat Feb 22 21:58:12 EST 2020

person4取完离开
Sat Feb 22 21:58:12 EST 2020

person7取完离开
person8进入柜台取钱
4510
Sat Feb 22 21:58:17 EST 2020

person8取完离开
person9进入柜台取钱
4511
Sat Feb 22 21:58:17 EST 2020

person9取完离开

根据时间,每次四个一次

四 事件

4.1 基本概念

阻塞事件 :

  1. e = Event()生成事件对象e
  2. e.wait()动态给程序加阻塞 , 程序当中是否加阻塞完全取决于该对象中的is_set()

[默认返回值是False]

  • 如果是True 不加阻塞
  • 如果是False 加阻塞

控制这个属性的值

  • set()方法 将这个属性的值改成True
  • clear()方法 将这个属性的值改成False
  • is_set()方法 判断当前的属性是否为True (默认上来是False)

4.2 基本语法

默认时False

from multiprocessing import Process,Event
e = Event()
print (e.is_set())

执行

[[email protected] python]# python3 test.py
False

使用阻塞

from multiprocessing import Process,Event
e = Event()
print (e.is_set())
e.wait(5)   #相当于sleep
print ("事件")

执行

[[email protected] python]# python3 test.py
False
事件

set

from multiprocessing import Process,Event
e = Event()
e.set()
print (e.is_set())
e.wait()
print ("事件")

执行,直接打印

[[email protected] python]# python3 test.py
True    #不加阻塞
事件

Claen

e = Event() # True
e.set()
e.wait()
print(123)
e.clear() # False
e.wait()
print(456)

执行,456不会打印,因为clean后时False

[[email protected] python]# python3 test.py
123

4.3 模拟红绿灯效果

from multiprocessing import Process,Event
import time
def traffic_light(e):
        #默认红灯先亮
        print ("red")
        while True:
                if e.is_set():
                        #当前时绿灯
                        time.sleep(2)
                        #等完2秒,变红灯
                        print("red")
                        e.clear()
                else:
                        #当前时红灯
                        time.sleep(2)
                        #等完2秒,变绿灯
                        print ("blue")
                        e.set()
e = Event()
traffic_light(e)

执行

[[email protected] python]# python3 test.py
red
blue
red
blue
red

模拟车辆遇到红灯停,绿灯行

from multiprocessing import Process,Event
import time,random
def traffic_light(e):
        #默认红灯先亮
        print ("red")
        while True:
                if e.is_set():
                        #当前时绿灯
                        time.sleep(2)
                        #等完2秒,变红灯
                        print("red")
                        e.clear()
                else:
                        #当前时红灯
                        time.sleep(2)
                        #等完2秒,变绿灯
                        print ("blue")
                        e.set()

def car(e,i):
        if not e.is_set():
                print ("The car%s is wait"%(i))
                e.wait()
        print("car%s is running"%(i))

e = Event()
p1 = Process(target=traffic_light,args=(e,))
p1.start()

for i in range(20):
        time.sleep(random.uniform(0,2))
        p2 = Process(target=car,args = (e,i))
        p2.start()

执行

[[email protected] python]# python3 test.py
red
The car0 is wait
blue
car0 is running
car1 is running
red
The car2 is wait
blue
car2 is running
car3 is running
car4 is running
red
The car5 is wait
blue
car5 is running
car6 is running
red
The car7 is wait
The car8 is wait
The car9 is wait
The car10 is wait
blue
car10 is running
car8 is running
car9 is running
car7 is running
car11 is running
red
The car12 is wait
blue
car12 is running
car13 is running
car14 is running
red
The car15 is wait
The car16 is wait
blue
car15 is running
car16 is running
car17 is running
car18 is running
red
The car19 is wait
blue
car19 is running
red

4.4 使用守护进程

from multiprocessing import Process,Event
import time,random
def traffic_light(e):
        #默认红灯先亮
        print ("red")
        while True:
                if e.is_set():
                        #当前时绿灯
                        time.sleep(2)
                        #等完2秒,变红灯
                        print("red")
                        e.clear()
                else:
                        #当前时红灯
                        time.sleep(2)
                        #等完2秒,变绿灯
                        print ("blue")
                        e.set()

def car(e,i):
        if not e.is_set():
                print ("The car%s is wait"%(i))
                e.wait()
        print("car%s is running"%(i))

e = Event()
p1 = Process(target=traffic_light,args=(e,))
p1.daemon = True
p1.start()

for i in range(20):
        time.sleep(random.uniform(0,2))
        p2 = Process(target=car,args = (e,i))
        p2.start()

执行

red
The car0 is wait
The car1 is wait
The car2 is wait
blue
car0 is running
car1 is running
car2 is running
car3 is running
car4 is running
car5 is running
car6 is running
red
The car7 is wait
The car8 is wait
The car9 is wait
The car10 is wait
blue
car8 is running
car7 is running
car9 is running
car10 is running
car11 is running
red
The car12 is wait
blue
car12 is running
car13 is running
car14 is running
red
The car15 is wait
blue
car15 is running
car16 is running
car17 is running
red
The car18 is wait
The car19 is wait

卡在这里不执行,是因为car已经跑完,进程不再执行,卡在e.wait这里

使用join

from multiprocessing import Process,Event
import time,random
def traffic_light(e):
        #默认红灯先亮
        print ("red")
        while True:
                if e.is_set():
                        #当前时绿灯
                        time.sleep(2)
                        #等完2秒,变红灯
                        print("red")
                        e.clear()
                else:
                        #当前时红灯
                        time.sleep(2)
                        #等完2秒,变绿灯
                        print ("blue")
                        e.set()

def car(e,i):
        if not e.is_set():
                print ("The car%s is wait"%(i))
                e.wait()
        print("car%s is running"%(i))

e = Event()
lst = []
p1 = Process(target=traffic_light,args=(e,))
p1.daemon = True
p1.start()

for i in range(20):
        time.sleep(random.uniform(0,2))
        p2 = Process(target=car,args = (e,i))
        p2.start()
        lst.append(p2)
for i in lst:
        i.join()
print("程序彻底结束;")

执行

red
The car0 is wait
The car1 is wait
blue
car1 is running
car0 is running
car2 is running
car3 is running
red
The car4 is wait
blue
car4 is running
car5 is running
car6 is running
car7 is running
red
The car8 is wait
The car9 is wait
blue
car9 is running
car8 is running
car10 is running
red
The car11 is wait
blue
car11 is running
car12 is running
car13 is running
car14 is running
red
The car15 is wait
blue
car15 is running
car16 is running
car17 is running
red
The car18 is wait
The car19 is wait
blue
car19 is running
car18 is running
程序彻底结束;

原文地址:https://www.cnblogs.com/zyxnhr/p/12354445.html

时间: 2024-08-03 14:27:39

041.Python守护进程,锁信号量和事件的相关文章

Python实例浅谈之五Python守护进程和脚本单例运行

一.简介 守护进程最重要的特性是后台运行:它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符.控制终端.会话和进程组.工作目录以及文件创建掩码等:它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启动,还可以由用户终端(通常是shell)执行. Python有时需要保证只运行一个脚本实例,以避免数据的冲突. 二.Python守护进程 1.函数实现 #!/usr/bin/env python #coding: utf-8

#python#守护进程的实现

找了整天,终于找到一个可以用的代码 #! /usr/bin/env python2.7 #encoding:utf-8 #@description:一个python守护进程的例子 #@tags:python,daemon import sys import os import time import atexit from signal import SIGTERM      class Daemon:   """   A generic daemon class.     

python 守护进程

daemon进程 守护进程 1.fork子进程,而后父进程退出,此时子进程会被init进程接管 2.修改子进程的工作目录,创建新进程组和新会话,修改umask 3.子进程再次fork一个进程,这个进程可以称为孙子进程,而后子进程退出 4.重定向孙子进程标准输入流,标准输出等 atexit程序退出 调用某个函数 kill  级别 python 守护进程,布布扣,bubuko.com

Python守护进程(多线程开发)

#!/usr/bin/python import sys,time,json,logging import Queue, threading, datetime from lib.base.daemon import Daemon from lib.queue.httpsqs.HttpsqsClient import HttpsqsClient from lib.db.DbMongodb import DbMongodb logging.basicConfig(level=logging.DEB

Python守护进程命令,为何被黑客钟意?整蛊、木马都用得上它!

考虑一下利用Python制作一个整蛊.木马软件,我提供思路.(清楚到没学过编程的人也理解) 1.首先一个黑客做一个整蛊或者木马软件,一定不会让你能够关闭它. 2.里面经常会附带欺骗的方法. 3.最终实现某种目的. 前段时间在抖音上看到个有趣的程序,看样子是VB写的,首先就要用到欺骗的方法,利用软件名称欺骗目标点击软件,打开后出现一个标签.两个按钮. 标签上写的是:我爱你,你爱我吗? 按钮:一个写爱,一个是不爱. 怎么办?一般人看到这种情况就直接点叉关闭软件了.然而人家程序员早就在代码里写了 窗口

python 线程(创建2种方式,守护进程,锁,死锁,递归锁,GIL锁,其他方式)

###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位    线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个进程中的资源共享,会涉及到安全问题,所以需要加锁解决 锁:牺牲了效率,保证了数据安全(重点) 死锁现象:出现在嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待(重点) 递归锁: 解决了死锁现象(重点) rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire+1,release

doraemon的python 守护进程和Process

### 9.4 Process模块 进程 ```python from multiprocess import Process p = Process(target=函数名,args=(参数1,)) 1.如何创建一个进程对象 对象和进程之间的关系: a.进程对象和进程并没有直接的关系 b.只是存储了一些和进程相关的内容 c.此时此刻,操作系统还没有接收到创建进程的指令 2.如何开启一个进程 通过p.start()开启一个进程,这个方法相当于给操作系统一个开启指令指令 start方法的异步非阻塞的

python 守护进程(daemon)

#!/usr/bin/env python # -*- coding:utf-8 -*- import sys, os '''将当前进程fork为一个守护进程    注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了    所有需要做的事情,包括重定向标准文件描述符,需要做的事情只有chdir()和umask()了 ''' def daemon(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):     #

linux下python守护进程编写和原理理解

原文地址: http://www.01happy.com/linux-python-daemon/ 守护进程英文为daemon,像httpd.mysqld.vsftpd最后个字母d其实就是表示daemon的意思. 守护进程的编写步骤: fork子进程,而后父进程退出,此时子进程会被init进程接管. 修改子进程的工作目录.创建新进程组和新会话.修改umask. 子进程再次fork一个进程,这个进程可以称为孙子进程,而后子进程退出. 重定向孙子进程的标准输入流.标准输出流.标准错误流到/dev/n