python网络编程之进程详解

目录
  • 1.进程
    • 1.1进程:
    • 1.2在python中创建进程
    • 1.3 使用multiprocessing创建进程
      • 1.3.1 单个进程时:
      • 1.3.2 多个子进程时:
      • 1.3.3 自定义进程类方法
    • 使用Process子类创建进程Process(target=test)实现多进程,复杂的要定义一个类继承Process,每次实例化这个类的时候就等同于实例化一个进程对象
    • 1.4 Pool进程池
  • 2. 验证进程是否能共享信息
  • 2.1 Queue(队列)模块:
    • 2.1.1 队列简介:
    • 2.2 实现进程间的通信
  • 总结

1.进程

它们的主要作用:多任务同时执行

1.1进程:

Windows打开的程序就是一个进程例如打开qq 打开微信

如果打开2个qq代表打开了2个进程

1.2在python中创建进程

只能Linux 使用os.fork()用这个可以创建多进程

Linux/Windows使用multiprocessing模块和Pool进程池(他俩是跨平台模块)

1.3 使用multiprocessing创建进程

1.3.1 单个进程时:

from multiprocessing import Process #从multiprocessing库中导入Process模块
#执行进程代码
#一个子进程
def test(interval):
    print("我是一个子进程")

#执行主程序
def main():
    print("主进程启动")
    p = Process(target=test,args=(1,)) #使用进程模块,目标参数target为子进程函数
    p.start() #启动子进程
    print("主进程结束")

if __name__ == '__main__':
    main()
"""
>>> runfile('D:/python_files/python_fiew/网络编程_01.py', wdir='D:/python_files/python_fiew')
主进程启动
主进程结束
我是一个子进程
"""

1.3.2 多个子进程时:

from multiprocessing import Process
import time,os
#子进程1
def child_1(interval):
    print("子进程(%s)开始执行,父进程为(%s)"%(os.getpid(),os.getpid())) #os.getpid()为获取进程号
    t_stat = time.time() #计时开始
    time.sleep(interval) #程序将被挂起n秒
    t_end = time.time() #计时结束
    print("子进程(%s)的执行时间为'%0.2f'秒"%(os.getpid(),t_end-t_stat))
#子进程2
def chlid_2(interval):
    print("子进程(%s)开始执行,父进程为(%s)"%(os.getpid(),os.getpid()))
    t_stat = time.time()
    time.sleep(interval)
    t_end = time.time()
    print("子进程(%s)的执行时间为(%0.2f)"%(os.getpid(),t_end-t_stat))

if __name__ == '__main__':
    print("-----父进程开始执行-------")
    print("父进程启动时,父进程PID为:(%s)"%(os.getpid()))  #打印父进程启动时父进程的PID
    p1 = Process(target=child_1,args=(1,)) #实例化子进程1
    p2 = Process(target=chlid_2,args=(1,)) #实例化子进程2
    p1.start() #启动子进程1
    p2.start() #启动子进程2
    #此时父进程仍然在执行
    print("pi.is_alive=%s"%(p1.is_alive()))  #p1.is_alive() 判断子进程p1是否还在执行,执行则返回ture
    print("p2_is_alive=%s"%(p2.is_alive()))
    #输出此时进程执行过程中的PID(进程号)
    print("执行过程中的p1的进程号p1.pid=%s"%(p1.pid))
    print("执行过程中的p2的进程号p2.pid=%s" % (p2.pid))
    print("---等待子进程结束----")
    p1.join() #等待子程序p1结束
    p2.join()
    print("父进程结束,此时父进程的进程号为:(%s)"%(os.getpid()))
#总结:#os.getpid()为获取进程号   #p1.is_alive() 判断子进程p1是否还在执行,执行则返回ture

由运行结果分析:子进程在执行的过程中,进程号不变。父进程号在启动时,和在结束所有子进程时 相同,而当子进程同时执行时,父进程号会动态变化。

挂起进程在 操作系统中可以定义为暂时被淘汰出 内存的进程,机器的资源是有限的,在资源不足的情况下,操作系统对在内存中的程序进行合理的安排,其中有的进程被暂时调离出内存,当条件允许的时候,会被操作系统再次调回内存,重新进入等待被执行的状态即就绪态,系统在超过一定的时间没有任何动作。

1.3.3 自定义进程类方法

使用Process子类创建进程Process(target=test)实现多进程,复杂的要定义一个类继承Process,每次实例化这个类的时候就等同于实例化一个进程对象

(解决上一个程序中两个子进程重复代码的问题)

from multiprocessing import Processimport time,os#继承Process类class SubProcess(Process):    def __init__(self,interval,name=""): #子类SubProcess的构造方法        Process.__init__(self) #Process.__init__(self) #继承父类的构造方法        self.interval = interval        self.name = name         #重写父类方法    def run(self):        print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getpid()))  # os.getpid()为获取进程号        t_stat = time.time()  # 计时开始        time.sleep(self.interval)  # 程序将被挂起n秒        t_end = time.time()  # 计时结束        print("子进程(%s)的执行时间为'%0.2f'秒" % (os.getpid(), t_end - t_stat))if __name__ == '__main__':    print("-----父进程开始执行-------")    print("父进程启动时,父进程PID为:(%s)"%(os.getpid()))  #打印父进程启动时父进程的PID    p1 = SubProcess(interval=1,name='ZARD1') #实例化子进程1    p2 = SubProcess(interval=2,name=('ZARD2')) #实例化子进程2    p1.start() #启动子进程1    p2.start() #启动子进程2    #此时父进程仍然在执行    print("pi.is_alive=%s"%(p1.is_alive()))  #p1.is_alive() 判断子进程p1是否还在执行,执行则返回ture    print("p2_is_alive=%s"%(p2.is_alive()))    #输出此时进程执行过程中的PID(进程号)    print("p1.name = %s"%(p1.name))    print("执行过程中的p1的进程号p1.pid=%s"%(p1.pid))    print("p2.name = %s" % (p2.name))    print("执行过程中的p2的进程号p2.pid=%s" % (p2.pid))    print("---等待子进程结束----")    p1.join() #等待子程序p1结束    p2.join()    print("父进程结束,此时父进程的进程号为:(%s)"%(os.getpid()))from multiprocessing import Process
import time,os

#继承Process类
class SubProcess(Process):
    def __init__(self,interval,name=""): #子类SubProcess的构造方法
        Process.__init__(self) #Process.__init__(self) #继承父类的构造方法
        self.interval = interval
        self.name = name

    #重写父类方法
    def run(self):
        print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getpid()))  # os.getpid()为获取进程号
        t_stat = time.time()  # 计时开始
        time.sleep(self.interval)  # 程序将被挂起n秒
        t_end = time.time()  # 计时结束
        print("子进程(%s)的执行时间为'%0.2f'秒" % (os.getpid(), t_end - t_stat))

if __name__ == '__main__':
    print("-----父进程开始执行-------")
    print("父进程启动时,父进程PID为:(%s)"%(os.getpid()))  #打印父进程启动时父进程的PID
    p1 = SubProcess(interval=1,name='ZARD1') #实例化子进程1
    p2 = SubProcess(interval=2,name=('ZARD2')) #实例化子进程2
    p1.start() #启动子进程1
    p2.start() #启动子进程2
    #此时父进程仍然在执行
    print("pi.is_alive=%s"%(p1.is_alive()))  #p1.is_alive() 判断子进程p1是否还在执行,执行则返回ture
    print("p2_is_alive=%s"%(p2.is_alive()))
    #输出此时进程执行过程中的PID(进程号)
    print("p1.name = %s"%(p1.name))
    print("执行过程中的p1的进程号p1.pid=%s"%(p1.pid))
    print("p2.name = %s" % (p2.name))
    print("执行过程中的p2的进程号p2.pid=%s" % (p2.pid))
    print("---等待子进程结束----")
    p1.join() #等待子程序p1结束
    p2.join()
    print("父进程结束,此时父进程的进程号为:(%s)"%(os.getpid()))

代码分析: 

1.4 Pool进程池

(解决当要创造成百上千个进程的情况)

例子: 有三个水槽 ,要接10桶水,我们最多只能同时接3盆,第10盆随便找一个盆,其他两个闲置。

from multiprocessing import Pool #导入进程池
import os,time

def task(name):
    print("子进程(%s)执行task %s..."%(os.getpid(),name))
    time.sleep(2) #休眠2秒

if __name__ == '__main__':
    print("---父进程(%s)启动---"%(os.getpid()))
    p = Pool(3)  #定义一个进程池,一次最多容纳三个进程,即一次最多可同时执行三个子进程
    for i in range(10):
        p.apply_async(task,args=(i,)) #使用非阻塞的方式调用task
    print("---等待所有子进程结束---")
    p.close() #关闭进程池,关闭后进程池不再接收新的请求
    p.join() #等待子进程结束
    print("全部子进程结束")

小结:定义一个进程池,并规定一个池子中可以同时执行多少个进程,可以实现多个进程分批次的执行。

注意:

(1)区分使用Process模块与使用进程池模块Pool的区别

(2)对于实例对象 p,p.start()表示开始执行进程;p.join()表示结束进程

(3)注意加强阻塞与非阻塞知识点的学习

2. 验证进程是否能共享信息

引例: 

from multiprocessing import Process

#子进程1
def plus():
    print("---子进程1开始执行---")
    global g_num #声明全局变量
    g_num += 50
    print("在子进程1下:g_num = %d"%(g_num))
    print("---子进程1结束运行---")

#子进程2
def minus():
    print("---子进程2开始执行---")
    global g_num #声明全局变量
    g_num -= 50
    print("在子进程2下:g_num = %d"%(g_num))
    print("---子进程2结束运行---")

g_num = 100 #赋值全局变量
if __name__ == '__main__':
    print("---主进程启动---")
    print("在主进程运行中,g_num = %d"%(g_num))
    child1 = Process(target=plus) #实例化子进程1
    child2 = Process(target=minus)  # 实例化子进程2
    child1.start() #启动子进程1
    child2.start()

    child1.join() #等待子进程结束
    child2.join()
    print("---主进程结束---")

由以上例子可见,对于进程1,2而言,全局变量g_num并不互相影响。即有如下关系:

那么就有如下问题了,思考:如何才能实现进程之间的通讯?

答:通过 multiprocessing Queue(队列), Pipes(管道), 接下来主要演示 Queue(队列)模块。

2.1 Queue(队列)模块:

2.1.1 队列简介:

1.新来的排队的在队尾

2.最前面的完成离队后,后面一个跟上

多进程队列的使用Queue, 本身他就是一个消息队列程序 :

实践: 当Queue(3)时:

from multiprocessing import Queue #导入队列模块
if __name__ == '__main__':
    q = Queue(3) #初始化一个Queue对象,最多只能接受3条put信息
    #消息写入队列
    q.put("消息1") #将此消息1写入队列
    q.put("消息2")
    print(q.full()) #q.full() 是验证队列是否已满  没满则返回False
    q.put("消息3")  #将此消息3写入队列
    print(q.full()) #q.full() 是验证队列是否已满  满了则返回Ture

    #利用try看看队列已满是否还可再塞入信息
    try:
        q.put("尝试塞入第4条信息",True,1) #可能出问题的代码
    except:
        print("尝试利用q.put()向队列中继续添加信息:")
        print("队列已满,现有消息数量为:%d,无法继续添加信息。"%(q.qsize()))  #q.qsize() 返回队列中的已有信息数量

    try:
        q.put_nowait("尝试塞入第4条信息")  # 可能出问题的代码
    except:
        print("尝试利用q.put_nowait()向队列中继续添加信息:")
        print("队列已满,现有消息数量为:%d,无法继续添加信息。" % (q.qsize()))  # q.qsize() 返回队列中的已有信息数量

    #获取(打印)队列中的信息
    if not q.empty():
        print("---从队列中读取信息---")
        for i in range(q.qsize()):  #循环打印队列信息
            print(q.get_nowait())  #q.get_nowait() 读取队列信息

解决:

 

当Queue(4)时,打印的结果如下,可见此时可继续向队列中塞入第4条信息。

小结:

multiprocessing.Process 可以创建多进程,使用multiprocessing Queue可以实现队列操作。

2.2 实现进程间的通信

from multiprocessing import Process,Queue
import time

#子进程1:向队列中写入数据
def write_date(q):
    if not q.full(): #若队列没满,则写入数据
        for i in range(5):
            date = "数据" + str(i)
            q.put(date) #向队列中写入数据
            print("已写入:%s" % date)
#子进程2:向队列中读取数据
def read_date(q):
    time.sleep(1)  # 休眠1s
    while not q.empty():
        print("读取:%s" % q.get(True, 2))  # 等待2s,如果还没读取到消息,抛出异常

#主程序
if __name__ == '__main__':
    print("---主程序启动---")
    q = Queue()  # 父进程创建Queue,并传给各个子进程
    write_child = Process(target=write_date,args=(q,)) # 实例化进程对象,其中args=(q,)表示把队列传给子进程1
    read_child = Process(target=read_date,args=(q,))
    write_child.start()  # 启动子进程1,写入
    read_child.start()  # 启动子进程2,读取
    write_child.join()  # 等待子进程1结束
    read_child.join()  # 等待子进程2结束
    print('-----父进程结束-----')
 

小结:

(1)进程之间可以通过队列来实现通信,但需要注意的是,队列中的信息遵循“先进先出”的原则。如上数据那样,先写入数据0,则最先读出的数据也是数据0;

(2)如:

在父进程中创建队列,再利用Process模块实例化子进程对象,target参数为子进程的函数名,args参数即为队列。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Python的进程及进程池详解

    目录 进程 进程和程序 进程的状态 Python中的进程 创建⼦进程 全局变量问题 守护进程 进程池 总结 进程 进程是操作系统分配资源的基本单元,是程序隔离的边界. 进程和程序 程序只是一组指令的集合,它本身没有任何运行的含义,它是静态的. 进程程序的执行实例,是动态的,有自己的生命周期,有创建有撤销,存在是暂时的. 进程和程序不是一一对应的,一个程序可以对应多个进程,一个进程也可以执行一个或者多个程序. 我们可以这样理解:编写完的代码,没有运行时称为程序,正在运行的代码,会启动一个(或多个)

  • Python全栈之进程和守护进程

    目录 1. 理解进程 2. 进程的语法 3. join自定义进程类 4. 守护进程 总结 1. 理解进程 进程的概念:(process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位. 资源分配:分配的是cpu和内存等物理资源 进程号是进程的唯一标识 同一个程序执行两次之后是两个进程 进程和进程之间的关系: 数据彼此隔离,通过socket通信 并行和并发: 并发:一个cpu同一时间不停执行多个程序 并行:多个cpu同一时间不停执行多个程序 cpu的进程调度的方法: # 先来先服务f

  • 详解python网络进程

    目录 一.多任务编程 二.进程 三.os.fork创建进程 3.1.进程ID和退出函数 四.孤儿和僵尸 4.1.孤儿进程 4.2.僵尸进程 4.3.如何避免僵尸进程的产生 五.Multiprocessing创建进程 5.1.multiprocessing进程属性 六.进程池 七.进程间通信(IPC) 7.1.管道通信(Pipe) 7.2.消息队列 7.3.共享内存 7.4.信号量(信号灯集) 一.多任务编程 意义:充分利用计算机的资源提高程序的运行效率 定义:通过应用程序利用计算机多个核心,达到

  • 关于对python中进程的几个概念理解

    目录 进程 僵尸进程 孤儿进程 守护进程 互斥锁 总结 进程 第一,进程是一个容器.每一个进程都有它自己的地址空间,一般情况下,包括文本区域( text region).数据区域(data region)和堆栈(stack region). 文本区域存储处理器执行的代码;数据区城存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储看活动过程调用的指令和本地变量. 第二,进程是一个"执行中的程序".程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才 能成为一个

  • python中进程间通信详细介绍

    目录 进程间通信(IPC) 管道通信(Pipe) 1.通信原理 2. 实现方法 共享内存 1.通信原理 2.实现方法 信号量(信号灯集) 1.通信原理 2. 实现方法 3.代码演示 进程间通信(IPC) 必要性 进程间空间独立,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信 常用进程间通信方法 管道 消息队列 共享内存 型号 信号量 套接字 管道通信(Pipe) 1.通信原理 在内存中开辟管道空间,生成管道操作对象,多个进程使用同一个管道对象进行读写即可实现通信 代码演示(w

  • python网络编程之进程详解

    目录 1.进程 1.1进程: 1.2在python中创建进程 1.3 使用multiprocessing创建进程 1.3.1 单个进程时: 1.3.2 多个子进程时: 1.3.3 自定义进程类方法 使用Process子类创建进程Process(target=test)实现多进程,复杂的要定义一个类继承Process,每次实例化这个类的时候就等同于实例化一个进程对象 1.4 Pool进程池 2. 验证进程是否能共享信息 2.1 Queue(队列)模块: 2.1.1 队列简介: 2.2 实现进程间的

  • python多线程、网络编程、正则表达式详解

    目录 闭包 多线程 主线程 线程阻塞 同步锁 网络编程 正则表达式 re.match函数 re.search方法 re.match与re.search的区别 re.findall()方法 正则表达式的特殊规则 闭包 account=0 def atm(num,flag): global account if flag: account=num+account print(account) else: account-=num print(account) atm(300,True) #存入300

  • 关于Python Socket编程的要点详解

    目录 前言 什么是socket? 如何在 Python 中创建 socket 对象? Python 的套接字库中有多少种可用的套接字方法? 服务器套接字可用的方法有哪些? 客户端套接字可用的方法有哪些? Python中可用的通用套接字方法有哪些? Python Socket 编程工作流程 Python 客户端-服务器通信示例代码 Python-Server.py Python-Client.py 如何运行客户端-服务器程序? 检查程序兼容性 快速总结--Python Socket 编程 总结 前

  • python网络爬虫 CrawlSpider使用详解

    CrawlSpider 作用:用于进行全站数据爬取 CrawlSpider就是Spider的一个子类 如何新建一个基于CrawlSpider的爬虫文件 scrapy genspider -t crawl xxx www.xxx.com 例:choutiPro LinkExtractor连接提取器:根据指定规则(正则)进行连接的提取 Rule规则解析器:将连接提取器提取到的连接进行请求发送,然后对获取的页面进行指定规则[callback]的解析 一个链接提取器对应唯一一个规则解析器 例:crawl

  • Python网络编程详解

    1.服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的"服务".它存在唯一目的就是等待客户端的请求,并响应它们(提供服务),然后等待更多请求. 2.客户端/服务器架构既可以应用于计算机硬件,也可以应用于计算机软件. 3.在服务器响应客户端之前,首先会创建一个通信节点,它能够使服务器监听请求. 一.套接字:通信端点 1.套接字 套接字是计算机网络数据结构,它体现了上节中所描述的"通信端点"的概念.在任何类型的通信开始之前,网络应用程序必须创建套接字

  • python 网络编程详解及简单实例

    python 网络编程详解 网络编程的专利权应该属于Unix,各个平台(如windows.Linux等).各门语言(C.C++.Python.Java等)所实现的符合自身特性的语法都大同小异.在我看来,懂得了Unix的socket网络编程,其他的形式的网络编程方法也就知道了.这句话说得还不太严谨.准确的应该说成懂得了socket编程的原理,网络编程也就知道了,不同之处就在于每个平台,每个语言都有自己专享的语法,我们直接灵活套用就行了. 下面是用python实现的最基本的网络编程的例子,即依托于客

  • python网络编程socket实现服务端、客户端操作详解

    本文实例讲述了python网络编程socket实现服务端.客户端操作.分享给大家供大家参考,具体如下: 本文内容: socket介绍 TCP: 服务端 客户端 UDP: 服务端 客户端 首发时间:2018-02-08 01:14 修改: 2018-03-20 :重置了布局,增加了UDP 什么是socket: socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为

  • Python基础之进程详解

    一.前言 进程,一个新鲜的字眼,可能有些人并不了解,它是系统某个运行程序的载体,这个程序可以有单个或者多个进程,一般来说,进程是通过系统CPU 内核数来分配并设置的,我们可以来看下系统中的进程: 可以看到,360浏览器是真的皮,这么多进程啊,当然可以这样来十分清楚的看进程线程使用情况: 通过任务管理器中的资源监视器,是不是很厉害了,哈哈哈.讲完了这些,再说说用法. 二.基本用法 进程能干什么,这是我们要深思熟虑的事情.我们都知道一个程序运行会创建进程,所以程序在创建这些进程的时候,为了让它们更能

  • Python实现简易Web爬虫详解

    简介: 网络爬虫(又被称为网页蜘蛛),网络机器人,是一种按照一定的规则,自动地抓信息的程序或者脚本.假设互联网是一张很大的蜘蛛网,每个页面之间都通过超链接这根线相互连接,那么我们的爬虫小程序就能够通过这些线不断的搜寻到新的网页. Python作为一种代表简单主义思想的解释型.面向对象.功能强大的高级编程语言.它语法简洁并且具有动态数据类型和高层次的抽象数据结构,这使得它具有良好的跨平台特性,特别适用于爬虫等程序的实现,此外Python还提供了例如Spyder这样的爬虫框架,BeautifulSo

  • python多线程和多进程关系详解

    关于多线程的大概讲解: 在Python的标准库中给出了2个模块:_thread和threading,_thread是低级模块不支持守护线程,当主线程退出了时,全部子线程都会被强制退出了.而threading是高级模块,用作对_thread进行了封装支持守护线程.在大部分状况下人们只需要采用threading这个高级模块即可. 关于多进程的大概讲解: 多进程是multiprocessing模块给出远程与本地的并发,在一个multiprocessing库的采用场景下,全部的子进程全是由一个父进程运行

随机推荐