python进程编程

多进程multiprocess模块

multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows.

这个模块的语法结构与threading模块基本相似。

查找到一个多进程的博客连接:https://www.cnblogs.com/Mr-Murray/p/9026955.html

from  multiprocessing import Process
import time
import os

def info():
    print("\033[35;1mThe time is %s\033[0m" % time.ctime())
    print("The parent is %s; The Child process is %s" % (os.getppid(), os.getpid()))

if __name__  == "__main__":
    for i in range(10):
        p = Process(target=info)
        p.start()
        p.join()

这段代码和之前用threading模块创建的多线程并没有任何的区别,但是如果在windows系统上执行时,必须加上if __name__ == "__main__":语句,原因如下:

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

以实例化的方式产生进程:
import os, time
from multiprocessing import Process

class Myprocess(Process):
    def __init__(self):
        super(Myprocess, self).__init__()

    def run(self):
        print("\033[35;1mThe time is %s\033[0m" % time.ctime())
        print("The parent is %s; The Child process is %s" % (os.getppid(), os.getpid()))

if __name__ == "__main__":
    p = Myprocess()
    p.start()#在调用p.start的时候,会自动执行类中的run方法,run方法是必不可少的。和threading类中的Thread中的run方法一样。

进程中的守护进程和threading模块中的守护线程是同一个意思,主进程结束的时候,子进程也会随之结束。

import os, time
from multiprocessing import Process

def fun1():
    print("starting %s".center(50,"-") % time.ctime())
    time.sleep(3)
    print("Stopping %s".center(50,"-") % time.ctime())

if __name__ == "__main__":
    p = Process(target=fun1)
    p.daemon = True
    p.start()
    time.sleep(1)

--------------------------------------------------------------------------
子进程中是要执行3s的,但主进程中只执行了1s,设置了守护进程之后,主进程结束,不管子进程的状态,子进程都要退出

利用多进程实现简易的socket并发连接。

server端代码:
import socket, time
from multiprocessing import Process

def handle(conn,addr):
    print("The connection is from %s at %s port" % addr)
    conn.send(b"Hello world")
    data = conn.recv(1024)
    conn.send(data)

if __name__ == "__main__":
    HOST = "localhost"
    PORT = 51423
    ADDR = (HOST, PORT)

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(ADDR)
    s.listen(5)

    while True:
        conn, addr = s.accept()
        p = Process(target=handle, args=(conn,addr)) # 进程间的数据是不共享的,因此需要把coon作为参数传递
        p.start()
    s.close()

client端代码:
import socket

HOST = "localhost"
PORT = 51423
ADDR = (HOST, PORT)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(ADDR)
data = s.recv(1024)
print(data.decode())
while True:
    info = input(">>>: ")
    s.send(info.encode())
    data = s.recv(1024)
    print(data.decode())

注意:

进程之间的数据是彼此之间不能互相访问的,因此conn必须作为参数传递。

进程之间的通信该怎么做?

进程中的队列和管道:

from multiprocessing import Process, Queue
from time import sleep
import random

# 利用进程写一个生成消费者模型,
# 生成者向队列插入一个随机数,消费者取出队列中的一个数值

def productor(q):
    while True:
        sleep(0.3)
        print("store an num")
        q.put(random.randint(1,100))

def consumer(q):
    while True:
        sleep(0.2)
        print("Getting an num")
        q.get()

if __name__ == "__main__":
    q = Queue()
    proc1 = Process(target=productor, args=(q,))
    proc2 = Process(target=consumer, args=(q,))
    proc1.start()
    proc2.start()

这只是一个简易模型,来说明队列在进程之间的通信。

这里的队列用法和线程中队列用法基本相同,只是一个用于进程通信,一个用于线程通信。

管道

管道的简单实用:

from multiprocessing import Process, Pipe

def f(conn):
    conn.send("Hello world")
    conn.close()

if __name__ == ‘__main__‘:
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print(parent_conn.recv())
    p.join()

manager

Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问。从而达到多进程间数据通信且安全。

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.

A manager returned by Manager() will support types listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue and Array.

一个简单实用的实例:

from multiprocessing import Process, Manager
import random

def f(list):
    list.append(random.randint(0,100))
    print(list)

if __name__ == "__main__":
    p_list = []
    with  Manager() as manager:
        l = manager.list()
        for i in range(10):
            p = Process(target=f,args=(l,))
            p.start()
            p_list.append(p)

        for res in p_list:
            res.join()

每一个进程给列表中添加一个数据,执行结果如下:

[95]
[95, 25]
[95, 25, 31]
[95, 25, 31, 70]
[95, 25, 31, 70, 9]
[95, 25, 31, 70, 9, 17]
[95, 25, 31, 70, 9, 17, 96]
[95, 25, 31, 70, 9, 17, 96, 71]
[95, 25, 31, 70, 9, 17, 96, 71, 96]
[95, 25, 31, 70, 9, 17, 96, 71, 96, 3]

进程池:

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

from  multiprocessing import Process, Pool
import time

def Foo(i):
    time.sleep(2)
    return i + 100

def Bar(arg):
    print(‘-->exec done:‘, arg)

if __name__ == "__main__":
    pool = Pool(5)

    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar)
        # pool.apply(func=Foo, args=(i,))

    print(‘end‘)
    pool.close()
    pool.join()

注意:其中在调用apply_async时候使用了callback回调函数

进程池详解,看到的一片博文:https://www.cnblogs.com/qiangyuge/p/7455814.html

原文地址:https://www.cnblogs.com/wxzhe/p/9101890.html

时间: 2024-10-24 19:54:49

python进程编程的相关文章

Python编程(二):Python进程、线程那点事儿

多进程,多线程编程 系统程序员.运维开发程序员在面试的时候经常会被问及一个常见问题: 进程是什么,线程是什么,进程和线程有什么区别? 不得不承认,这么多年了.这个问题依旧是个很难以招架的问题,简单地说: 进程和线程有很多类似的性质,他们都可以被CPU作为一个单元进行调度,他们都拥有自己独立的栈(stack)等等.因此线程也被称作LWP(Lightweight Process,轻量级进程):对应的进程也可以被称作为HWP(Heavyweight Process,重量级进程),从线程的角度看,进程就

[Python网络编程]浅析守护进程后台任务的设计与实现

在做基于B/S应用中,经常有需要后台运行任务的需求,最简单比如发送邮件.在一些如防火墙,WAF等项目中,前台只是为了展示内容与各种参数配置,后台守护进程才是重头戏.所以在防火墙配置页面中可能会经常看到调用cgi,但真正做事的一般并不是cgi,比如说执行关机命令,他们的逻辑如下: (ps:上图所说的前台界面包含通常web开发中的后端,不然也没有socket一说) 为什么要这么设计 你可能疑惑为什么要这么设计,我觉得理由如下: 首先有一点说明,像防火墙等基本上都运行在类Linux平台上 1.安全问题

[ Python - 14 ] python进程及线程编程

什么是进程: 简单来讲,进程就是操作系统中运行的程序或任务,进程和程序的区别在于进程是动态的,而程序是静态的.进程是操作系统资源管理的最小单位. 什么是线程: 线程是进程的一个实体,是cpu调度和分派的最小单位,它是比进程更小的能独立运行的基本单位,线程本身不拥有资源,但它可以与同属于一个进程的线程共享进程的资源所拥有的全部资源. python多线程编程与GIL: 为了更有效的利用多核处理,就出现了多线程编程,但是问题是线程间数据的一致性和状态的同步如果得到保证,因此python解析器引入了GI

python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终端 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

python网络编程基础(线程与进程、并行与并发、同步与异步)

python网络编程基础(线程与进程.并行与并发.同步与异步) 目录 线程与进程 并行与并发 同步与异步 线程与进程 进程 前言 进程的出现是为了更好的利用CPU资源使到并发成为可能. 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费.聪明的老大们就在想若在任务A读取数据时,让任务B执行,当任务A读取完数据后,再切换到任务A执行.注意关键字切换,自然是切换,那么这就涉及到了状态的保存,状态的恢复,加上任务A与任务B所需要的

进程,操作系统,Python并发编程之多进程

1.进程基础知识 1.程序:若干文件 2.进程:一个正在执行的文件,程序 3.进程被谁执行:cpu最终运行指定的程序 4.操作系统调度作用:将磁盘上的程序加载到内存,然后交由CPU去处理,一个CPU正在运行的一个程序,就叫开启了一个进程 2.操作系统 1.操作系统:存在于硬盘与软件之间,管理.协调.控制软件与硬件的交互 2.操作系统的作用:将一些复杂的硬件封装成简单的借口,便于使用;合理地调度分配多个进程与cpu的关系,让其有序化 3.操作系统发展史 ①第一代电子计算机(1940-1955) 二

Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信

目录 Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信 1.昨日回顾 2.僵尸进程和孤儿进程 2.1僵尸进程 2.2孤儿进程 2.3僵尸进程如何解决? 3.互斥锁,锁 3.1互斥锁的应用 3.2Lock与join的区别 4.进程之间的通信 进程在内存级别是隔离的 4.1基于文件通信 (抢票系统) 4.2基于队列通信 Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信 1.昨日回顾 1.创建进程的两种方式: 函数, 类. 2.pid: os.getpid() os.get

Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池

目录 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 2.死锁现象与递归锁 2.1死锁现象 2.2递归锁 3.信号量 4.GIL全局解释器锁 4.1背景 4.2为什么加锁 5.GIL与Lock锁的区别 6.验证计算密集型IO密集型的效率 6.1 IO密集型 6.2 计算密集型 7.多线程实现socket通信 7.1服务端 7.2客户端 8.进程池,线程池 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 #生产者消

Python并发编程之进程2

引言 本篇介绍Python并发编程下的进程,先介绍进程的相关知识,然后对python中multiprocessing模块进行介绍(Process.Pipe.Queue以及 Lock). 进程(process) 在面向线程设计的系统(如当代多数操作系统.Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器. 进程拥有自己独立的内存空间,所属线程可以访问进程的空间. 程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 例如,我们在PyCharm开发环境中写