广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python进程和线程的概念是什么
  • 399
分享到

Python进程和线程的概念是什么

2023-06-02 02:06:38 399人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要介绍“python进程和线程的概念是什么”,在日常操作中,相信很多人在Python进程和线程的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python进程和线程的概念是什么”的疑惑有所

这篇文章主要介绍“python进程和线程的概念是什么”,在日常操作中,相信很多人在Python进程和线程的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python进程和线程的概念是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

并发编程就是实现让程序同时执行多个任务,而如何实现并发编程呢,这里就涉及到进程和线程这两个概念。

对于操作系统来说,一个任务(或者程序)就是一个进程(Process),比如打开一个浏览器是开启一个浏览器进程,打开微信就启动了一个微信的进程,打开两个记事本,就启动两个记事本进程。

进程的特点有:

  • 操作系统以进程为单位分配存储空间, 每个进程有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据;

  • 进程可以通过 fork 或者 spawn 方式创建新的进程来执行其他任务

  • 进程都有自己独立的内存空间,所以进程需要通过进程间通信机制(IPC,Inter-Process Communication)来实现数据共享,具体的方式包括管道、信号、套接字、共享内存区等

一个进程还可以同时做多件事情,比如在 Word 里面同时进行打字、拼音检查、打印等事情,也就是一个任务分为多个子任务同时进行,这些进程内的子任务被称为线程(Thread)。

因为每个进程至少需要完成一件事情,也就是一个进程至少有一个线程。当要实现并发编程,也就是同时执行多任务时,有以下三种解决方案:

  • 多进程,每个进程只有一个线程,但多个进程一起执行多个任务;

  • 多线程,只启动一个进程,但一个进程内开启多个线程;

  • 多进程+多线程,即启动多个进程,每个进程又启动多个线程,但这种方法非常复杂,实际很少使用

注意:真正的并行执行多任务只有在多核 CPU 上才可以实现,单核 CPU 系统中,真正的并发是不可能的,因为在某个时刻能够获得CPU的只有唯一的一个线程,多个线程共享了CPU的执行时间。

Python 是同时支持多进程和多线程的,下面就分别介绍多进程和多线程。

多进程

在 Unix/linux 系统中,提供了一个 fork() 系统调用,它是一个特殊的函数,普通函数调用是调用一次,返回一次,但 fork 函数调用一次,返回两次,因为调用该函数的是父进程,然后复制出一份子进程了,最后同时在父进程和子进程内返回,所以会返回两次。

子进程返回的永远是 0 ,而父进程会返回子进程的 ID,因为父进程可以复制多个子进程,所以需要记录每个子进程的 ID,而子进程可以通过调用 getpid() 获取父进程的 ID。

Python 中 os 模块封装了常见的系统调用,这就包括了 fork ,代码示例如下:

import osprint('Process (%s) start...' % os.getpid())# Only works on Unix/Linux/Mac:pid = os.fork()if pid == 0: print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))else: print('I (%s) just created a child process (%s).' % (os.getpid(), pid))

运行结果:

Process (876) start...I (876) just created a child process (877).I am child process (877) and my parent is 876.

由于 windows 系统中是不存在 fork ,所以上述函数无法调用,但 Python 是跨平台的,所以也还是有其他模块可以实现多进程的功能,比如 multiprocessing模块。

multiprocess

multiprocessing 模块中提供了 Process 类来代表一个进程对象,接下来用一个下载文件的例子来说明采用多进程和不用多进程的差别。

首先是不采用多进程的例子:

def download_task(filename): '''模拟下载文件''' print('开始下载%s...' % filename) time_to_download = randint(5, 10) sleep(time_to_download) print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))def download_without_multiprocess(): '''不采用多进程''' start = time() download_task('Python.pdf') download_task('nazha.mkv') end = time() print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__': download_without_multiprocess()

运行结果如下,这里用 randint 函数来随机输出当前下载文件的耗时,从结果看,程序运行时间等于两个下载文件的任务时间总和。

开始下载Python.pdf...Python.pdf下载完成! 耗费了9秒开始下载nazha.mkv...nazha.mkv下载完成! 耗费了9秒总共耗费了18.00秒.

如果是采用多进程,例子如下所示:

def download_task(filename): '''模拟下载文件''' print('开始下载%s...' % filename) time_to_download = randint(5, 10) sleep(time_to_download) print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))def download_multiprocess(): '''采用多进程''' start = time() p1 = Process(target=download_task, args=('Python.pdf',)) p1.start() p2 = Process(target=download_task, args=('nazha.mkv',)) p2.start() p1.join() p2.join() end = time() print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__': download_multiprocess()

这里多进程例子中,我们通过 Process 类创建了进程对象,通过 target 参数传入一个函数表示进程需要执行的任务,args 是一个元组,表示传递给函数的参数,然后采用 start 来启动进程,而 join 方法表示等待进程执行结束。

运行结果如下所示,耗时就不是两个任务执行时间总和,速度上也是大大的提升了。

开始下载Python.pdf...开始下载nazha.mkv...Python.pdf下载完成! 耗费了5秒nazha.mkv下载完成! 耗费了9秒总共耗费了9.36秒.

Pool

上述例子是开启了两个进程,但如果需要开启大量的子进程,上述代码的写法就不合适了,应该采用进程池的方式批量创建子进程,还是用下载文件的例子,但执行下部分的代码如下所示:

import osfrom multiprocessing import Process, Poolfrom random import randintfrom time import time, sleepdef download_multiprocess_pool(): '''采用多进程,并用 pool 管理进程池''' start = time() filenames = ['Python.pdf', 'nazha.mkv', 'something.mp4', 'lena.png', 'lol.avi'] # 进程池 p = Pool(5) for i in range(5): p.apply_async(download_task, args=(filenames[i], )) print('Waiting for all subprocesses done...') # 关闭进程池 p.close() # 等待所有进程完成任务 p.join() end = time() print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__': download_multiprocess_pool()

代码中 Pool 对象先创建了 5 个进程,然后 apply_async 方法就是并行启动进程执行任务了,调用 join() 方法之前必须先调用 close() ,close() 主要是关闭进程池,所以执行该方法后就不能再添加新的进程对象了。然后 join() 就是等待所有进程执行完任务。

运行结果如下所示:

Waiting for all subprocesses done...开始下载Python.pdf...开始下载nazha.mkv...开始下载something.mp4...开始下载lena.png...开始下载lol.avi...nazha.mkv下载完成! 耗费了5秒lena.png下载完成! 耗费了6秒something.mp4下载完成! 耗费了7秒Python.pdf下载完成! 耗费了8秒lol.avi下载完成! 耗费了9秒总共耗费了9.80秒.

子进程

大多数情况,子进程是一个外部进程,而非自身。在创建子进程后,我们还需要控制子进程的输入和输出。

subprocess 模块可以让我们很好地开启子进程以及管理子进程的输入和输出。

下面是演示如何用 Python 演示命令 nslookup www.python.org,代码如下所示:

import subprocessprint('$ nslookup www.python.org')r = subprocess.call(['nslookup', 'www.python.org'])print('Exit code:', r)

运行结果:

$ nslookup www.python.orgServer: 192.168.19.4Address: 192.168.19.4#53Non-authoritative answer:www.python.org canonical name = python.map.fastly.net.Name: python.map.fastly.netAddress: 199.27.79.223Exit code: 0

如果子进程需要输入,可以通过 communicate() 进行输入,代码如下所示:

import subprocessprint('$ nslookup')p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)output, err = p.communicate(b'set q=mx\npython.org\nexit\n')print(output.decode('utf-8'))print('Exit code:', p.returncode)

这段代码就是执行命令 nslookup 时,输入:

set q=mxpython.orgexit

运行结果:

$ nslookupServer: 192.168.19.4Address: 192.168.19.4#53Non-authoritative answer:python.org mail exchanger = 50 mail.python.org.Authoritative answers can be found from:mail.python.org internet address = 82.94.164.166mail.python.org has AAAA address 2001:888:2000:d::a6Exit code: 0

进程间通信

进程之间是需要通信的,multiprocess 模块中也提供了 Queue、Pipes 等多种方式来交换数据。

这里以 Queue 为例,在父进程创建两个子进程,一个往 Queue 写入数据,另一个从 Queue 读取数据。代码如下:

import osfrom multiprocessing import Process, Queueimport randomfrom time import time, sleep# 写数据进程执行的代码:def write(q): print('Process to write: %s' % os.getpid()) for value in ['A', 'B', 'C']: print('Put %s to queue...' % value) q.put(value) sleep(random.random())# 读数据进程执行的代码:def read(q): print('Process to read: %s' % os.getpid()) while True: value = q.get(True) print('Get %s from queue.' % value)def ipc_queue(): ''' 采用 Queue 实现进程间通信 :return: ''' # 父进程创建Queue,并传给各个子进程: q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 启动子进程pw,写入: pw.start() # 启动子进程pr,读取: pr.start() # 等待pw结束: pw.join() # pr进程里是死循环,无法等待其结束,只能强行终止: pr.terminate()if __name__ == '__main__': ipc_queue()

运行结果如下所示:

Process to write: 24992Put A to queue...Process to read: 22836Get A from queue.Put B to queue...Get B from queue.Put C to queue...Get C from queue.

到此,关于“Python进程和线程的概念是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: Python进程和线程的概念是什么

本文链接: https://www.lsjlt.com/news/228532.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python进程和线程的概念是什么
    这篇文章主要介绍“Python进程和线程的概念是什么”,在日常操作中,相信很多人在Python进程和线程的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python进程和线程的概念是什么”的疑惑有所...
    99+
    2023-06-02
  • java线程、进程和Synchronized的概念
    这篇文章主要介绍“java线程、进程和Synchronized的概念”,在日常操作中,相信很多人在java线程、进程和Synchronized的概念问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java线程、...
    99+
    2023-05-30
    java
  • Linux的进程线程及调度的概念是什么
    这篇“Linux的进程线程及调度的概念是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Linux的进程线程及调度的概念是...
    99+
    2023-06-28
  • JavaScript单线程的概念是什么
    这篇文章主要介绍“JavaScript单线程的概念是什么”,在日常操作中,相信很多人在JavaScript单线程的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Ja...
    99+
    2022-10-19
  • Python进程池基本概念是什么
    这篇文章主要介绍“Python进程池基本概念是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python进程池基本概念是什么”文章能帮助大家解决问题。前言:创建进程池可以形象地理解为创建一个并行...
    99+
    2023-06-29
  • Linux中进程与线程的概念以及区别是什么
    本篇文章为大家展示了Linux中进程与线程的概念以及区别是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。linux进程与线程的区别,早已成为IT界经常讨论但热度不减的话题。无论你是初级程序员,还...
    99+
    2023-06-05
  • Java多线程基础概念是什么
    本篇内容主要讲解“Java多线程基础概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程基础概念是什么”吧!并发与并行并行,表示两个线程同时做事情。并发,表示一会做这个事情,一...
    99+
    2023-06-17
  • linux僵尸进程的概念是什么
    本篇内容介绍了“linux僵尸进程的概念是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!linux僵尸进程是一个已经终止但是其父进程尚未...
    99+
    2023-07-02
  • python和jquery的概念是什么
    这篇文章主要介绍“python和jquery的概念是什么”,在日常操作中,相信很多人在python和jquery的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”py...
    99+
    2022-10-19
  • swoole协程的概念是什么
    本篇内容介绍了“swoole协程的概念是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!swoole协程是更加轻量级的线程,一个线程可以拥...
    99+
    2023-06-29
  • Java进程调度算法的概念是什么
    这篇“Java进程调度算法的概念是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java进程调度算法的概念是什么”文章吧...
    99+
    2023-07-02
  • Python协程概念及其用法是什么
    这篇文章将为大家详细讲解有关Python协程概念及其用法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。对于协程,我表示其效率确非多线程能比,但本人对此了解并不深入,因此最近几日参考了一...
    99+
    2023-06-17
  • Java中的线程生命周期核心概念是什么
    本篇内容主要讲解“Java中的线程生命周期核心概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中的线程生命周期核心概念是什么”吧!Java多线程在Java语言中,多线程是由线程的...
    99+
    2023-07-02
  • golang协程调度的概念是什么
    Golang中的协程调度是指Goroutine(Go语言中的轻量级线程)的调度和执行过程。Golang使用了一种称为M:N调度的模型...
    99+
    2023-10-26
    golang
  • Python中keyerror的概念是什么
    在Python中,KeyError是一种异常,当我们使用字典或集合中不存在的键时,就会引发KeyError。换句话说,当我们尝试通过...
    99+
    2023-08-08
    Python
  • oltp和olap的概念是什么
    OLTP(在线事务处理)和OLAP(在线分析处理)是数据处理领域中常用的两个概念。OLTP是指用于处理实时事务的数据库和系统。它主要...
    99+
    2023-10-12
    oltp olap
  • php和html的概念是什么
    本篇内容主要讲解“php和html的概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php和html的概念是什么”吧! PH...
    99+
    2022-10-19
  • asp和javascript的概念是什么
    本篇内容主要讲解“asp和javascript的概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“asp和javascript的概念是什么”吧! ...
    99+
    2022-10-19
  • docker和jenkins的概念是什么
    这篇文章主要讲解了“docker和jenkins的概念是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“docker和jenkins的概念是什么”吧! ...
    99+
    2022-10-19
  • span和div的概念是什么
    这篇“span和div的概念是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“span和...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作