python多进程和多线程一起使用_Python:多进程和多线程

在现实社会,我们经常需要一种场景,就是同时有多个事情需要执行,如在浏览网页的同时需要听音乐。比如说在跳舞的时候要唱歌。

同样的,在程序中我们也可能需要这种场景。如下面我们以同时听音乐和浏览网页为例。

def network():

while True:

print("正在上网~~~")

time.sleep(1)def sing():

while True:

print("正在听歌……")

time.sleep(1)

if __name__ == "__main__":

network()

sing()

执行代码,我们发现代码并没有按照我们的想法执行,而是,一直执行上网的代码,这样就无法完成我们想要的效果。

如果你想要同时听音乐和浏览网页两件事,就需要一个新的方式来完成,这个方式就是----多任务。

多任务是咋回事呢?

什么叫做多任务呢?简单的说,就是操作系统(OS)可以同时运行多个任务。如你可以一边浏览网页,一边听着歌,同时还可以使用画板画着画,这个就是多任务。其实我们的操作系统就是多任务,只是我们都没有注意罢了。

单核CPU中:

1、时间片轮换

2、优先级别调度

3、多核CPU中:

4、并发

5、并行

Fork子进程

编写完的代码,在没有运行的情况下,称之为程序。

正在运行的代码,就成为了进程。

进程,除了包含代码外,还需要运行环境等,所以和程序是存在区别的。

Python在os模块上封装了常用的系统调用,其中就包括了fork,我们可以很轻松地在Python代码中创建进程。

# 注意,下面代码只能在Linux、Mac系统上运行,window下不支持运行!!!

import osimport time# 使用os模块的fork方法可以创建一个新的进程

pid = os.fork()if pid == 0:

while True:

print("son process", pid) # 子进程代码

time.sleep(1)

else:

while True:

print("main process", pid) # 父进程代码

time.sleep(1)

Python中的fork() 函数可以获得系统中进程的PID ( Process ID ),返回0则为子进程,否则就是父进程,然后可以据此对运行中的进程进行操作;

但是强大的 fork() 函数在Windows版的Python中是无法使用的。。。只能在Linux系统中使用,比如 Ubuntu 15.04,Windows中获取父进程ID可以用 getpid()。

getpid、getppid

我们可以使用os模块的getpid来获取当前进程的进程编号,同样也可以使用os.getppid()方法案来获取当前进程的父进程编号。

import osimport time# 使用os模块的fork方法可以创建一个新的进程

pid = os.fork()

if pid == 0:

while True:

print("我是子线程,我的编号是%s,我的父进程编号是%s(os.getpid(),os.getppid()))

time.sleep(1)

else:

while True:

print("我是父线程,我的编号是%s,我的子进程编号是%s" %(os.getpid(), pid))

time.sleep(1)

使用os模块中的getpid()方法,可以得到当前线程的编号,使用getppid()方法可以得到该线程的父级编号。

多进程修改全局变量多进程修改全局变量

import os

import time

# 使用os模块的fork方法可以创建一个新的进程

pid = os.fork()

if pid == 0:

while True:

print("我是子线程,我的编号是%s,我的父进程编号是%s" %(os.getpid(),os.getppid()))

time.sleep(1)

else:

while True:

print("我是父线程,我的编号是%s,我的子进程编号是%s" %(os.getpid(), pid))

time.sleep(1)

使用os模块中的getpid()方法,可以得到当前线程的编号,使用getppid()方法可以得到该线程的父级编号。

多进程修改全局变量

import os

# 定义一个全局变量

num = 0

pid = os.fork()

if pid == 0:

# 子进程

num += 1

print("子进程~~~~~~",num)

else:

#父进程

num += 1

print("父进程~~~~~~", num)

输出结果如下

父进程~~~~~~ 1

子进程~~~~~~ 1

由此可见,进程间是无法共享数据的。

注意:多个进程间,每个进程的所有数据(包括全局变量)都是各自拥有一份的,互不影响。

完成最开始的任务

import os

import time

def network():

for x in range(5):

print("正在上网~~~")

time.sleep(1)

def singe():

for x in range(5):

print("正在听歌……")

time.sleep(1)

pid = os.fork()

if pid == 0:

network()

else:

singe()

print("程序结束~~~")

多个fork问题

上面的所有程序中,我们使用了fork函数,生成了两个进程(一个主进程、一个子进程),但是如果我们在程序中需要多个进程呢?如两次调用fork函数,会生成三个进程吗?

import os,time

res = os.fork()

if res == 0:

print("一个子线程")

else:

print("主线程")

ret = os.fork()

if ret == 0:

print("第三个线程")

else:

print("第四个线程")

结果如下

主线程

第四个线程

第三个线程

一个子线程

第三个线程

第四个线程

我们发现,主线程和子线程各执行了一次,但是第三个和第四个都执行了两次,为什么了,看下面的图。

5067c5238fb6?utm_content=note&utm_medium=reader_share

1.png

主进程和子进程的执行顺序

其实通过上面的代码,我们已经发现了,主进程和子进程的执行顺序是没有规律的,这个不受程序员的控制,有操作系统的调度算法来控制。

multiprocessing

前面我们使用os.fork()方法实现了多进程,但是这种方案只能在Linux下运行,window环境下是无法运行的,那么有没有可以实现在任何平台都能运行的多进程了,有!Python为大家提供了multiprocessing模块用来实现多进程。

函数实现方式

from multiprocessing import Process

import os

def run():

print("这个是一个独立的进程",os.getpid(),os.getppid())

if __name__ == "__main__":

print("代码开始运行……")

task = Process(target=run)

task.start() # 启动进程

print("代码运行结束……",os.getpid())

结果如下

5067c5238fb6?utm_content=note&utm_medium=reader_share

2.png

我们发现主进程结束后,子进程才结束,说明我们确实开辟了一个独立的进程。

from multiprocessing import Process

import os

def run(msg):

for x in range(5):

print("这个是一个独立的进程",os.getpid(),os.getppid())

print("传递的参数是:",msg)

else:

print("子进程结束了……")

if __name__ == "__main__":

print("代码开始运行……")

# target表示独立进程的方法

#args表示要传递的参数,注意:args的类型是元组,也支持列表list

task = Process(target=run,args=("这个是参数",))

task.start() # 启动进程

print("代码运行结束……",os.getpid())

args为调用的子进程的函数的参数,注意类型是一个元组。

from multiprocessing import Process

import os

def run(msg):

for x in range(5):

print("这个是一个独立的进程",os.getpid(),os.getppid())

print("传递的参数是:",msg)

else:

print("子进程结束了……")

if __name__ == "__main__":

print("代码开始运行……")

# target表示独立进程的方法

#args表示要传递的参数,注意:args的类型是元组

task1 = Process(target=run,args=("这个是参数1",))

task1.start() # 启动进程

task2 = Process(target=run, args=("这个是参数2",))

task2.start() # 启动进程

task3 = Process(target=run, args=("这个是参数3",))

task3.start() # 启动进程

print("代码运行结束……",os.getpid())

多个进程启动还是一样,执行的顺序同样不可控。

(主进程等待子进程版):

join方法表示只有子进程执行完成后,主进程才能结束。主进程会等待子进程完成后,自身才会执行完成。

from multiprocessing import Process

import os,time

def run(msg):

print("子进程开始执行了……")

time.sleep(3)

print("子进程执行end了……")

if __name__ == "__main__":

print("代码开始运行……")

task1 = Process(target=run,args=("这个是参数1",))

print(task1.is_alive()) # is_alive()方法判断进程是否结束

task1.join() # 表示这个子进程执行完成,主进程才能继续向下执行

print(task1.is_alive())

print("代码运行结束……",os.getpid())

常用方法

from multiprocessing import Process

import os,time

def run(msg):

print("子进程开始执行了……")

time.sleep(3)

print("子进程执行end了……")

if __name__ == "__main__":

print("代码开始运行……")

# name表示我们认为的为这个子进程取个名称,

# 如果不写,默认是Process-n n从1开始

task1 = Process(target=run,args=("这个是参数1",),name="liujianhong")

task1.start() # 启动进程

print(task1.is_alive()) # is_alive()方法判断进程是否结束

task1.join() # 表示这个子进程执行完成,主进程才能继续向下执行

print(task1.name) # 得到子进程的名称

task1.terminate() # 强制结束进程

print(task1.is_alive())

print("代码运行结束……",os.getpid())

多个进程使用不同的方法版

from multiprocessing import Process

import os,time

def run(msg):

print("子进程1开始执行了……")

time.sleep(3)

print("子进程1执行end了……")

def run2(msg):

print("子进程2开始执行了……")

time.sleep(3)

print("子进程2执行end了……")

if __name__ == "__main__":

print("代码开始运行……")

task1 = Process(target=run,args=("这个是参数1",))

task1.start() # 启动进程

task2 = Process(target=run2, args=("这个是参数2",))

task2.start() # 启动进程

print("代码运行结束……",os.getpid())

类实现方式

在Python中,很多的方案都提供了函数和类两种实现方式,如:装饰器、自定义元类。同样多进程也有两种实现,前面我们已经看了使用函数实现的方式,下面我们使用类来实现以下呗。

进程类的实现非常的简单,只要继承了Process类就ok了,重新该类的run方法,run方法里面的代码,就是我们需要的子进程代码。

from multiprocessing import Process

import time

class MyProcess(Process):

# 重写run方法即可

def run(self):

print("一个子进程开始运行了")

time.sleep(1)

print("一个子进程开始运行结束了")

if __name__ == '__main__':

task = MyProcess()

task.start()

print("主进程结束了……")

在进程类的实现中如果想要初始化一些前面我们提到过的参数,如进程名称等,可以使用init借助父类来完成。

from multiprocessing import Process

import time

class MyProcess(Process):

def __init__(self,name):

super().__init__(name=name)

# 重写run方法即可

def run(self):

print("一个子进程开始运行了")

time.sleep(1)

print("一个子进程开始运行结束了")

if __name__ == '__main__':

task = MyProcess("刘建宏")

task.start()

print(task.name)

print("主进程结束了……")

进程池Pool

当我们需要的进程数量不多的时候,我们可以使用multiprocessing的Process类来创建进程。但是如果我们需要的进程特别多的时候,手动创建工作量太大了,所以Python也为我们提供了Pool(池)的方式来创建大量进程。

from multiprocessing import Pool

import os,time

def run(msg):

print("开始一个子线程运行了……")

time.sleep(1)

print("开始一个子线程运行结束了……")

if __name__ == "__main__":

pool = Pool(3) # 表示初始化一个进程池,最大进程数为5

for x in range(10):

pool.apply_async(run, args=("hello pool",))

print("------start----")

pool.close() # 关闭池

pool.join() # 等待所有的子进程完成,必须放在close后面

print("-------end------")

注意:一般我们使用apply_async这个方法,表示非阻塞的运行,一旦使用了apply方法表示阻塞式执行任务,此时就是单任务执行了(一般不会使用,特殊场景才会使用)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/419805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python字典怎么换行_Python字典如何换行

原标题:Python字典如何换行Python字典换行的方法如下:1、换行时保证行尾是逗号即可a {"key0": "val0","key1": "val1","key2": "val2"}2、在长度不影响阅读的情况下这种写法也是允许的&am…

回复《我要阻止做java开发的男朋友去创业型公司工作吗?》园友问题

真的非常开心能收到这么多园友的关心,看到这么多的回复顿感身边处处充满爱。也非常感谢大家踊跃的帮我出谋划策,小女子在此有礼了! 我先来回答一下性别的问题(前面已经暴露了……),我是前端程序媛。大三时和…

java date转sql date_java.util.Date和java.sql.Date转换(转)

Date 的类型转换:首先记住java.util.Date 为 java.sql.Date的父类1.将java.util.Date 转换为 java.sql.Datejava.lang.ClassCastException: java.util.Date cannot be cast to java.sql.DateDate dnew Date(); //java.util.Datenew java.sql.Date(d.getTime()) //…

Kaggle Bike Sharing Demand Prediction – How I got in top 5 percentile of participants?

Kaggle Bike Sharing Demand Prediction – How I got in top 5 percentile of participants? Introduction There are three types of people who take part in a Kaggle Competition: Type 1: Who are experts in machine learning and their motivation is to compete with…

java 组合对象_Java 中组合模型之对象结构模式的详解

Java 中组合模型之对象结构模式的详解一、意图将对象组合成树形结构以表示”部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。二、适用性你想表示对象的部分-整体层次结构你希望用户忽略组合对象与单个对象的不同,用户将统一使用组…

前端学习(1525):简化模板代码

app.vue <template><div id"app"></div> </template><script> export default {name: app,data () {return {}} } </script><style>运行结果

java 整型长度_java int的长度是多少

int&#xff1a;int 数据类型是32位、有符号的以二进制补码表示的整数&#xff1b; (推荐学习&#xff1a;java课程)最小值是 -2,147,483,648(-2^31)&#xff1b;最大值是 2,147,483,647(2^31 - 1)&#xff1b;一般地整型变量默认为 int 类型&#xff1b;默认值是 0 &#xff1…

java命令行 引用jar包_java命令行引用jar包

一个简单的测试程序&#xff1a;import java.sql.*;/*** Created by N3verL4nd on 2017/4/17.*/public class JdbcDemo{public static void main(String[] args) {Connection conn;Statement stmt;ResultSet rs;String url "jdbc:mysql://localhost:3306/weibo?" &…

DataTable操作

DataTable操作 一 复制DataTable中符合条件的DataRow到新的DataTable中 One&#xff1a; DataTable TableTemp new DataTable();//临时table DataTable tableAd new Web.DAL.FreeBase().TranSQLGetTable("select a.ClassName,b.ParentId,b.Name,b.Pic,b.Url,b.Sorts fro…

java水印图片_JAVA实用案例之图片水印开发

写在最前面上周零零碎碎花了一周的时间研究水印的开发&#xff0c;现在终于写了个入门级的Demo&#xff0c;做下笔记同时分享出来供大家参考。Demo是在我上次写的 JAVA实用案例之文件导入导出(POI方式) 框架基础上搭建的&#xff0c;基于SpringSpringMVC。如果有错误还请大家指…