python之进程

1,什么是进程呢?

进程(Process)是计算机中的关于某数据集合上的一次运算,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是程序的实体。

动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。
多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。

进程的特征

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
程序可以作为一种软件资料长期存在,而进程是有一定生命期的。
程序是永久的,进程是暂时的。

程序与进程的区别

同一个程序执行两次,就会在操作系统中出现两个进程,可以同时运行一个软件,分别做不同的事情也不会混乱。

2,进程调度

要想多个进程交替运行,操作系统必须对这些进程进行调度,需要进程调度算法。

(1)先来先服务调度算法

(2)短作业优先调度算法

(3)时间片轮转发

(4)多级反馈队列:设置多个就绪队列,为各个队列赋予不同优先级。优先级逐个降低,当一个程序在时间片仍未执行完,便加入到下一对列,直到执行完。每当有新进程进来,优先执行。

3,进程的并行与并发

并行:并行是指两者同时执行,例:比赛,两个人都在不停的往前跑(资源够用。比如三个线程,四核的cpu)

并发:并发是指在资源有限的情况下,两者交替轮流使用资源。(单核cpu)A走一段hou

,让B走一段,B用完后在给A,交替使用。

区别:

并行:是从微观上,就是在一个精确的时间片刻,有不同的程序在执行,要求必须有多个处理器。

并发:是从宏观上,在一个时间段可以看出同时执行的,比如一个服务器同时处理多个session

4,同步异步阻塞非阻塞

操作系统调度算法控制时,程序会进入几个状态:就绪,运行,阻塞。

(1)同步与异步

同步:完成一个任务需要依赖另一个任务,只等别依赖的任务完成后,才能执行自己的。

异步:不需要等待依赖任务完后成,只需通知被依赖的任务执行。

(2)阻塞非阻塞

阻塞:程序停止不在执行

5,进程的创建与结束

multiprocess模块

(1)

Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)

强调:
1. 需要使用关键字的方式来指定参数
2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

参数介绍:
1 group参数未使用,值始终为None
2 target表示调用对象,即子进程要执行的任务
3 args表示调用对象的位置参数元组,args=(1,2,‘egon‘,)
4 kwargs表示调用对象的字典,kwargs={‘name‘:‘egon‘,‘age‘:18}
5 name为子进程的名称

1 p.start():启动进程,并调用该子进程中的p.run()
2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
4 p.is_alive():如果p仍然运行,返回True
5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 

方法

1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
2 p.name:进程的名称
3 p.pid:进程的pid
4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
5 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

属性

在Windows操作系统中由于没有fork(linux操作系统中创建进程的机制),在创建子进程的时候会自动 import 启动它的这个文件,而在 import 的时候又执行了整个文件。因此如果将process()直接写在文件中就会无限递归创建子进程报错。所以必须把创建子进程的部分使用if __name__ ==‘__main__’ 判断保护起来,import 的时候  ,就不会递归运行了。

注意事项

# from  multiprocessing import Process
# import os
# def func(i):
#     print(‘%d:子进程%d干的事,父进程:%d‘%(i,os.getpid(),os.getppid()))
#
# if __name__==‘__main__‘:
#     p_lst=[]
#     for i in range(10):
#         p=Process(target=func,args=(i,))
#         p.start()
#         p_lst.append(p)
#     # p.join()                         #等子进程执行完,才执行下面的
#     for p in p_lst:p.join()
#     print(‘---主进程---‘)

多进程同时运行,子进程的执行顺序不是根据启动顺序决定的。

(2)通过继承Process类开启进程。

import os
from multiprocessing import Process

class MyProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):                                 #必须有run方法
        print(os.getpid())
        print(‘%s 正在和女主播聊天‘ %self.name)

p1=MyProcess(‘wupeiqi‘)
p2=MyProcess(‘yuanhao‘)
p3=MyProcess(‘nezha‘)

p1.start() #start会自动调用run
p2.start()
# p2.run()
p3.start()

p1.join()
p2.join()
p3.join()

print(‘主线程‘)

注:进程之间的数据不是共享的(数据的隔离问题)

from multiprocessing import Process

def work():
    global n
    n=0
    print(‘子进程内: ‘,n)

if __name__ == ‘__main__‘:
    n = 100
    p=Process(target=work)
    p.start()
    print(‘主进程内: ‘,n)

5,守护进程

子进程会随主进程的结束而结束。

主进程创建守护进程

       其一:守护进程会在主进程代码执行结束后终止

       其二:守护进程内无法再开子进程,否则抛异常。

# start  开启一个进程
# join   用join可以让主进程等待子进程结束

# 守护进程
# 守护进程会随着主进程的代码执行结束而结束
# 正常的子进程没有执行完的时候主进程要一直等着
import time
from multiprocessing import Process
def func():
    print(‘--‘*10)
    time.sleep(15)
    print(‘--‘*10)

def cal_time():
    while True:
        time.sleep(1)
        print(‘过去了1秒‘)

if __name__ == ‘__main__‘:
    p = Process(target=cal_time)
    p.daemon = True     # 一定在开启进程之前设置
    p.start()
    p2 = Process(target=func)  # 15s
    p2.start()
    for i in range(100):    # 10s
        time.sleep(0.1)
        print(‘*‘*i)
    p2.join()

# 守护进程的进程的作用:
    # 会随着主进程的代码执行结束而结束,不会等待其他子进程
# 守护进程 要在start之前设置
# 守护进程中 不能再开启子进程

6,锁

  当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题

from multiprocessing import Lock

import time
import json
import random
from multiprocessing import Lock
from multiprocessing import Process

def search(i):
    with open(‘ticket‘) as f:
        print(i,json.load(f)[‘count‘])

def get(i):
    with open(‘ticket‘) as f :
        ticket_num=json.load(f)[‘count‘]
    time.sleep(random.random())
    if ticket_num>0:
        with open(‘ticket‘,‘w‘) as f:
            json.dump({‘count‘:ticket_num-1},f)
        print(‘%s买到票了‘%i)
    else:
        print(‘%s没买到票‘%i)
def task(i,lock):
    search(i)
    lock.acquire()   #锁,钥匙
    get(i)
    lock.release()   #还钥匙

if __name__==‘__main__‘:
    lock=Lock()
    for i in range(20):
        p=Process(target=task,args=(i,lock))
        p.start()

抢票的例子

#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
虽然可以用文件共享数据实现进程间通信,但问题是:
1.效率低(共享数据基于文件,而文件是硬盘上的数据)
2.需要自己加锁处理

#因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。
队列和管道都是将数据存放于内存中
队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,
我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

7,信号量(from multiprocessing import Semaphore)

信号量基于内部的计数器,可以有多个锁钥匙。

import random
import time
from multiprocessing import Process
from multiprocessing import Semaphore

def sing(i,sem):
    sem.acquire()
    print(‘%s :进去 ktv ‘%i)
    time.sleep(random.randint(2,8))
    print(‘%s : 离开 ktv‘%i)
    sem.release()

if __name__==‘__main__‘:
    sem=Semaphore(5)          #钥匙数,参数可以设置
    for i in range(20):
        Process(target=sing,args=(i,sem)).start()

例子

8,事件(from multiprocessing import Event)

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

clear:将“Flag”设置为False
set:将“Flag”设置为True

介绍

# import time
# import random
# from multiprocessing import Process
# from multiprocessing import Event
#
# def traffic_light(e):
#     while True:
#         if e.is_set():         # e.is_set()是否阻塞 True就是绿灯 False就是红灯
#             time.sleep(3)
#             print(‘红灯亮‘)
#             e.clear()
#         else:
#             time.sleep(3)
#             print(‘绿灯亮‘)
#             e.set()
# def car(i,e):
#     e.wait()
#     print(‘%s车通过‘%i)
#
# if __name__==‘__main__‘:
#     e=Event()
#     tra=Process(target=traffic_light,args=(e,))
#     tra.start()
#     for i in range(100):
#         if i%6 == 0:
#             time.sleep(random.randint(1,3))
#         car_pro=Process(target=car,args=(i,e))
#         car_pro.start()

例子

9,队列(from multiprocessing import Queue)

创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。

Queue([maxsize])
创建共享的进程队列。maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。底层队列使用管道和锁定实现。另外,还需要运行支持线程以便队列中的数据传输到底层管道中。
Queue的实例q具有以下方法:

q.get( [ block [ ,timeout ] ] )
返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 如果设置为False,将引发Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。

q.get_nowait( )
同q.get(False)方法。

q.put(item [, block [,timeout ] ] )
将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。block控制阻塞行为,默认为True。如果设置为False,将引发Queue.Empty异常(定义在Queue库模块中)。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引发Queue.Full异常。

q.qsize()
返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。

q.empty()
如果调用此方法时 q为空,返回True。如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。

q.full()
如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的(参考q.empty()方法)。

方法介绍

#1.进程之间通信 可以使用multiprocessing 的 Queue模块
#2.队列有两种创建方式 第一种不传参数 这个队列就没有长度限制 ;传参数,创建一个有最大长度限制的队列
#3.提供两个重要方法;put get
#4.qsize

from multiprocessing import Process
from multiprocessing import Queue

# def q_put(q):
#     q.put(‘hello‘)
#
# def q_get(q):
#     print(q.get())
#
# if __name__ ==‘__main__‘:
#     q = Queue()
#     p = Process(target=q_put,args=(q,))
#     p.start()
#     p1 = Process(target=q_get, args=(q,))
#     p1.start()

生产者消费者模型

# 通过队列实现了 主进程与子进程的通信   子进程与子进程之间的通信
# 生产者消费者模型

# 我要生产一个数据 然后 给一个函数 让这个函数依赖这个数据进行运算  拿到结果  —— 同步过程

# 做包子 和 吃包子
import time
def producer(q):  # 生产者
    for i in  range(100):
        q.put(‘包子%s‘%i)

def consumer(q): #  消费者
    for i in range(100):
        time.sleep(1)
        print(q.get())

if __name__ == ‘__main__‘:
    q = Queue(10)   # 托盘
    p = Process(target=producer,args=(q,))
    p.start()
    c1 = Process(target=consumer, args=(q,))
    c2 = Process(target=consumer, args=(q,))
    c1.start()
    c2.start()

# 首先 对于内存空间来说 每次只有很少的数据会在内存中
# 对于生产与消费之间的不平衡来说
    # 增加消费者或者增加生产者来调节效率

原文地址:https://www.cnblogs.com/glf1160/p/8406014.html

时间: 2024-10-09 00:33:13

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 3 进程池与回调函数

Python 3 进程池与回调函数 一.进程池 在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间.多进程是实现并发的手段之一,需要注意的问题是: 很明显需要并发执行的任务通常要远大于核数 一个操作系统不可能无限开启进程,通常有几个核就开几个进程 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行) 例如当被操作对象数目不大时,可以直接利用multiprocessing中的Proces

python 守护进程

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

【Python】使用Supervisor来管理Python的进程

1.问题描述 需要一个python的服务程序在后台一直运行,不能让该进程被杀死,即使被杀死也要能及时自动重启.如:有一个python的程序:test.py ,通过命令:python test.py来运行程序,但是它会受命令行的中断而中断.所以我们需要一个方法来保证该程序一直在后台运行. 2.解决方法 以前经常用命令:nohup python test.py & 来保证其在后台运行不中断,但是这也不能保证一直运行. 下面介绍用supervisor来管理python的进程,保证其在后台一直运行不中断

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写的,首先就要用到欺骗的方法,利用软件名称欺骗目标点击软件,打开后出现一个标签.两个按钮. 标签上写的是:我爱你,你爱我吗? 按钮:一个写爱,一个是不爱. 怎么办?一般人看到这种情况就直接点叉关闭软件了.然而人家程序员早就在代码里写了 窗口

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使用进程池管理进程和进程间通信

与线程池类似的是,如果程序需要启动多个进程,也可以使用进程池来管理进程.程序可以通过 multiprocessing 模块的 Pool() 函数创建进程池,进程池实际上是 multiprocessing.pool.Pool 类. 进程池具有如下常用方法: 1.apply(func[, args[, kwds]]):将 func 函数提交给进程池处理.其中 args 代表传给 func 的位置参数,kwds 代表传给 func 的关键字参数.该方法会被阻塞直到 func 函数执行完成. 2.app

Python学习进程(13)文件与IO

    本节介绍基本的IO函数和文件的读写操作.     (1)读取键盘输入: Python用于读取键盘输入的函数有两个:raw_input与input. 1)raw_input函数 从标准输入读取一个行,并返回一个字符串(去掉结尾的换行符) >>> str=raw_input("请输入一个字符串") 请输入一个字符串 >>> str=raw_input("请输入一个字符串:\n") 请输入一个字符串: my name is Me