进程和线程(Python版)

进程和线程

1、进程和线程的概念

进程

​ 是正在执行的程序,是多任务操作系统中执行任务的基本单元,是包含了程序指令和相关资源的集合,是程序执行时的一个实例,在程序运行时创建的。

线程

​ 线程是进程的执行单元。在大多数程序中,可能只有一个主线程,但是为了提高效率,有些程序会采用多线程,在系统中所有线程看起来都是同时执行的。

在这里插入图片描述

线程和进程的对比

​ 进程是重量级的,具体包括进程映像的结构,执行细节以及进程间切换的方法。在进程中,需要处理的问题包括进程间通信,临界区管理和进程调度等,这些特性使得生成一个进程的开销是比较大的。
​ 线程是轻便的,线程之间共享很多资源,容易进行通信,生成一个线程的开销很小,但是线程会出现死锁,数据同步和实现复杂的问题

并发编程解决方案
  • 启动多个进程,每个进程只有一个线程,但多个进程可以一块执行多个任务

  • 启动一个进程,在一个进程中启动多个线程,这样,多个线程也可以一起执行多个任务

  • 启动多个进程,每个进程再启动多个线程,这样执行的任务更多,但是这种方法更加复杂,很少采用

python在多进程处理CPU密集型程序(各种循环处理,计数等等)比较友好,在多线程处理IO密集型代码(文件处理,网络爬虫等)比较友好

2、进程的开发

python标准库中相关模块
模块 介绍
subprocess python基本库中多线程编程相关模块,适用于外部进程交互,调用外部进程
multiprocessing 核心机制是fork,重开一个进程,首先会把父进程的代码copy重载一遍
threading python基本库多线程管理相关模块
subprocess模块
run 方法
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
  • args:表示要执行的命令。必须是一个字符串,字符串参数列表。
  • stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
  • timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
  • check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常。
  • encoding: 如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
  • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
import subprocess 
# 调用外部命令(如window的dir,ipconfig,linux等命令等)
runcmd=subprocess.run('dir D:',encoding='utf-8',shell=True)
# 显示d盘下所有的目录
print(runcmd)

run方法可用文件句柄形式传参

import subprocess
f=open(r'd:\\sxt2.txt','w+')
run_cmd=subprocess.run('python',stdin=f,stdout=subprocess.PIPE,shell=True)
#调用python程序命令
run_cmd.stdin='print("你好")'
f.write(run_cmd.stdin)
f.close()
print(run_cmd.stdout.decode('utf-8'))

优点:可以通过执行python程序,对stdin传参,通过stdout输出
缺点:需要提前指定文件,并不方便,对进程的使用并不友好

Popen 方法
class(类) subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,restore_signals=True,start_new_session=False, pass_fds=(),*, encoding=None, errors=None)

常用参数

  • args:shell命令,可以是字符串或者序列类型,调用的程序(如:list,元组)
  • bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
    0:不使用缓冲区
    1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
    正数:表示缓冲区大小
    负数:表示使用系统默认的缓冲区大小。
  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
  • shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。
import subprocess
popen=subprocess.Popen('python',stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
# 调用python这个程序命令,从标准输入里面写入,在标准输出输出
popen.stdin.write('print("hello")\n'.encode('utf-8'))
popen.stdin.write('import math\n'.encode('utf-8'))
popen.stdin.write("print(math.sqrt(4))\n".encode('utf-8'))
popen.stdin.close()
result=popen.stdout.read().decode('utf-8')
popen.stdout.close()
print(result)

Popen 对象方法

  • poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None。
  • wait(timeout): 等待子进程终止,设定timeout,超过这个时间就自动结束。
  • communicate(input,timeout): 和子进程交互,发送和读取数据。
  • terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。
  • kill(): 杀死子进程。发送 SIGKILL 信号到子进程
multprocessing模块
class(类) multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={
   }, daemon=None)

常用参数

  • group:一般都为None

  • target:run()方法调用的函数

  • name:表示进程调用的名字

  • args:表示目标调用的元组

  • kwargs:表示目标调用的字典

  • daemon:表示守护线程,当父进程结束后,子进程会强制结束

常用方法

  • run():表示进程活动的方法。你可以在子类中重载此方法。标准 run方法用传递给对象构造函数的可调用对象作为目标参数(如果有),分别从 argskwargs 参数中获取顺序和关键字参数。
  • start():启动进程活动。这个方法每个进程对象最多只能调用一次。它会将对象的 放法安排在一个单独的进程中调用。
  • join([timeout])如果可选参数 timeout 是 None (默认值),则该方法将阻塞,直到调用 join方法的进程终止。如果 timeout 是一个正数,它最多会阻塞 timeout 秒。请注意,如果进程终止或方法超时,则该方法返回 None 。检查进程的 exitcode 方法的进程终止。如果 timeout 是一个正数,它最多会阻塞 timeout 秒。请注意,如果进程终止或方法超时,则该方法返回 None
  • close()关闭 Process对象,释放与之关联的所有资源。
创建子进程(函数)
import multiprocessing
import os
import time

def fun(name):
    print("该进程的序号",name)
    print("父进程的id",os.getpid())# getpid获取当前进程的id地址
    print("子进程的id",os.getpid())
    print()
    time.sleep(3) # 停格三秒
if __name__ == '__main__':
    # 创建多个子进程来调用函数
    start=time.time()
    for i in range(10):
        p=multiprocessing.Process(target=fun,args=('进程%d'%i,)) # 创建一个子进程
        p.start() # 开启一个子进程
    print("进程完成")
    # 进程之间并不会出现堵塞的现象,父进程会跟着子进程所有的代码结束才会完全停止
    end=time.time()
    print(end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值