【摸鱼笔记】subprocess,用子进程访问外部命令

news/2024/11/15 0:28:45/

subprocess是一个非常强大的模块,它能通过启动新进程的方式执行外部命令、访问系统Shell、管道等。

同时也能捕获这些新进程的输出和错误信息;

subprocess模块是Python的标准库中的一部分,支持 Python 3.5 及 3.5 以上版本;

3.5 以下版本需要额外安装;

执行外部命令

subprocess.run()

subprocess.run() 用于运行外部命令并等待其完成;

capture_output: 抓取输出;capture_output 参数 与 stdout,stderr 相关,

在不传入capture_output 和 stdout、stderr 的默认情况下,subprocess不会抓取 stdout 和 stderr,并且返回值对象里这两个属性为
None。

传入stdout=PIPE 和 stderr=PIPE 或者 stdout=PIPE、stderr=PIPE 其中一个,subprocess会对应着抓取它们;

如果希望抓取并将两个流合并在一起,可以使用 stdout=PIPE 和 stderr=STDOUT;

直接传入 capture_output=True,subprocess会stdout、stderr两个都抓取;

因为在capture_output=True时,内置的 Popen 对象将自动用 stdout=PIPE 和 stderr=PIPE 创建管道。

所以stdout 和 stderr 参数不应当与 capture_output 同时传入。

check: 返回状态检查;check 参数和子进程运行退出状态码有关

当子进程退出时 return code(状态码) 不为 0,则会触发 CalledProcessError异常;

退出的 return code 会保存到 CalledProcessError.returncode 属性中,

如果 stdout、stderr有被抓取,则 stdout 和 stderr 也会在 CalledProcessError.stdout 和 CalledProcessError.stderr属性里;

timeout :超时时间,如果传入 timeout,并且进程花费的时间超出 timeout,则会触发TimeoutExpired异常;

text: 功能类似 universal_newlines 参数,

默认不传入的情况下,subprocess.run() 返回的stdout、stderr是字节类型,

当text或者universal_newlines为True,stdout、stderr输出是字符串类型;

cwd: 指定 subprocess 子进程工作路径;

input :向子进程传入的参数,可选参数,以下是官方文档的解释

input 参数将被传递给 Popen.communicate() 以及子进程的 stdin。它必须是一个字节序列;

如果指定了 encoding 或 errors 或者将 text 设置为 True,那么也可以是一个字符串。

当使用此参数时,在创建内部 Popen 对象时将自动带上 stdin=PIPE,并且不能再手动指定 stdin 参数。

一般使用

python">import subprocesscomplete = subprocess.run(["ipconfig", "/all"],capture_output=True,text=True)
print(complete.stdout)

拼接参数

如果命令需要接受参数,可以将它们作为列表的一部分传递给subprocess.run()或subprocess.Popen()。

例如,要将文件名作为参数传递给命令,可以这样做:

python">import subprocesssub_path = "data_lake"
complete = subprocess.run(["dir", sub_path],shell=True,capture_output=True,text=True,cwd="E:\\VsCodeProjects\\")
print(complete.stdout)

指定路径

使用cwd参数来指定执行外部命令的工作目录。例如,要在特定目录中执行命令,可以这样做:

python">import subprocesscomplete = subprocess.run(["dir"],shell=True,capture_output=True,text=True,cwd="E:\\VsCodeProjects\\")
print(complete.stdout)

使用Shell命令

默认情况下,subprocess不会使用Shell来执行命令。这是出于安全考虑,以防止潜在的Shell注入攻击。但有些情况下,可能需要使用Shell来执行命令,可以将shell参数设置为True。

python">import subprocesscomplete = subprocess.run(["dir", "nonexistent"],shell=True,capture_output=True,text=True)
print("标准输出:")
print(complete.stdout)
print("标准错误:")
print(complete.stderr)

输入输出

标准输出

python">import subprocess# 使用 capture_output
complete = subprocess.run(["ipconfig", "/all"],capture_output=True,text=True)
print(complete.stdout)# 单独使用 stdout
complete = subprocess.run(["ipconfig", "/all"],stdout=subprocess.PIPE,text=True)
print(complete.stdout)# 单独使用 stdout 输出到txt
with open("stdout_tmp.txt", mode="w", encoding="utf8") as fw:complete = subprocess.run(["ipconfig", "/all"],stdout=fw,text=True)print(complete.stdout)# stdout 与 stderr 合并
complete = subprocess.run(["ipconfig", "/all"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
print(complete.stdout)

标准输入

subprocess模块还可以将数据传递给外部命令的标准输入。要实现这一点,可以使用stdin参数,并将其设置为一个文件对象或一个字节串。

python">import subprocessinput_data = "Hello, subprocess!"
complete = subprocess.run(["findstr", "subprocess"],input=input_data,capture_output=True,text=True)
print(complete.stdout)

标准错误

与标准输出类似,subprocess还可以捕获标准错误信息。要捕获标准错误,请使用stderr参数。

python">import subprocesscomplete = subprocess.run(["dir", "nonexistent"],shell=True,capture_output=True,text=True)
print("标准输出:")
print(complete.stdout)
print("标准错误:")
print(complete.stderr)

子进程运行状态检查

执行外部命令时,通常需要处理错误。以下是一些处理错误的常用方法

抓取stderr内容

python">import subprocesscomplete = subprocess.run(["dir", "nonexistent"],shell=True,capture_output=True,text=True)
if complete.returncode != 0:print("stderr:", complete.stderr)

触发 CalledProcessError

python">import subprocesstry:complete = subprocess.run(["dir", "nonexistent"],shell=True,check=True,capture_output=True,text=True)print("stdout:", complete.stdout)
except subprocess.CalledProcessError as e:print("CalledProcessError:")print("CalledProcessError.returncode:", e.returncode)print("CalledProcessError.stdout:", e.stdout)print("CalledProcessError.stderr:", e.stderr)

超时处理

subprocess还允许您设置执行命令的超时时间,以防止命令运行时间过长。要实现这一点,您可以使用timeout参数。

python">import subprocesstry:complete = subprocess.run(["pause"],shell=True,timeout=12,capture_output=True,text=True)print(complete.stdout)
except subprocess.TimeoutExpired as e:print("TimeoutExpired")print("TimeoutExpired.stdout", e.stdout)print("TimeoutExpired.stderr", e.stderr)

subprocess.Popen()

subprocess.Popen()提供了更多的灵活性,允许与进程进行交互,而不仅仅是等待它完成。

args 应当是一个程序参数的序列或者是一个单独的字符串或 path-like object。

默认情况下,如果 args 是序列则要运行的程序为 args 中的第一项。

stdin, stdout 和 stderr 分别指定被执行程序的标准输入、标准输出和标准错误文件句柄;

可以传入的值有 None, PIPE, DEVNULL, 或者文件对象;

当使用默认设置 None 时,将不会进行任何重定向;

PIPE 表示应当新建一个连接子进程的管道;

DEVNULL 表示将使用特殊文件 os.devnull;

stderr 还可以为 STDOUT,stdout 和 stderr 合并;

shell:默认为 False, 指定是否使用 shell 执行程序;

如果 cwd 不为 None,此函数在执行子进程前会将当前工作目录改为 cwd,cwd 可以是一个字符串、字节串或 路径类对象。

text: 功能类似 universal_newlines 参数,

默认不传入的情况下,subprocess.Popen() 返回的stdout、stderr是字节类型,

当text或者universal_newlines为True,stdout、stderr输出是字符串类型;

encoding,errors: 在默认情况下,文件对象将以二进制模式打开。

如果指定了 encoding 或 errors,或者如果 text 为真值,

则文件对象 stdin, stdout 和 stderr 将使用指定的 encoding 和 errors 以文本模式打开。

python">import subprocess# 执行命令
process = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)# 读取标准输出和错误
out, err = process.communicate()print("标准输出:")
print(out)print("标准错误:")
print(err)

管道和重定向

subprocess还可以创建管道,将一个命令的输出连接到另一个命令的输入。这在处理复杂的数据处理任务时非常有用。

例如,要将一个命令的输出传递给另一个命令,

python">import subprocess# 创建第一个命令的进程
subprocess1 = subprocess.Popen(["dir", "E:\\PyCharmProjects\\nicole\\"],shell=True,stdout=subprocess.PIPE,text=True)# 创建第二个命令的进程,将第一个命令的输出连接到它的输入
subprocess2 = subprocess.Popen(["findstr", "favicon"],shell=True,stdin=subprocess1.stdout,stdout=subprocess.PIPE,text=True)# 从第二个命令的标准输出中读取结果
complete = subprocess2.communicate()[0]
print(complete)

子进程通信

subprocess模块同时读取和写入标准输入和输出。这对于与外部进程进行双向通信非常有用。

以下是一个示例,演示如何使用subprocess进行双向通信:

python">import subprocess# 创建命令进程
process = subprocess.Popen(["python", "-u"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)# 写入数据到标准输入
with process.stdin as std_in:std_in.write("print('Hello from child process')\n")# 读取并打印标准输出
output, errors = process.communicate()
print("输出:", output, errors)

http://www.ppmy.cn/news/1503485.html

相关文章

JavaScript/.Net/.Java三端对称加AES算法加解密

文章目录 前言一、JavaScript AES二、.Net AES三、Java AES总结 前言 AES(Advanced Encryption Standard),即高级加密标准,是一种广泛应用的对称密钥加密算法,由美国国家标准与技术研究院(NIST)…

node环境安装electron

文章目录 前言 一、安装node 二、使用步骤 1.配置npm环境 2.安装electron 总结 前言 Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台的桌面应用程序。它基于 Node.js 和 Chromium,被 Atom 编辑器和许多其他应用程序使用。 Electron 兼容 Mac、Win…

【Rust光年纪】完整解读:六大Rust HTTP客户端库全面对比

Rust语言中的HTTP客户端库大比拼:全面对比与分析 前言 随着Rust语言在系统编程领域的不断发展,对于HTTP客户端库的需求也日益增长。本文将介绍几个用于Rust语言的HTTP客户端库,分别从简介、安装与配置以及API概览等方面进行详细对比和总结。…

Zookeeper源码剖析-启动类

文章目录 从启动脚本开始分析ZooKeeper启动脚本 `zkServer.sh` 分析1. 脚本位置2. 脚本结构3. 主要部分3.1 检测环境变量3.2 加载配置文件3.3 设置环境变量3.4 日志配置3.5 启动和停止命令3.6 启动ZooKeeper3.7 停止ZooKeeper4. 其他功能5. 调用方式总结ZooKeeper的 QuorumPeer…

2.5 C#视觉程序开发实例2----图片内存管理

2.5 C#视觉程序开发实例2----图片内存管理 1 目标效果视频 mat-buffer 2 Mat 数组的定义 3 图片内存使用场合说明 3.1 程序加载或者切换程序时 3.2 设定时,注册图片 例如注册一个线速的图片 注册流程说明 3.3 外部触发时采集最新图片或者按钮点击时触发拍照 …

程序员转型人工智能:从“996”困境到拥抱光明未来

前言 在这个充满挑战与机遇的时代,各行各业的辛酸各有不同,而程序员群体无疑有着自己的独特体验。他们学习着普通人难以理解的计算机语言,工作在“996”的高压环境中,还未及中年就可能面临“聪明绝顶”的尴尬。面对行业的快速更新…

electron 主进程和渲染进程

最近在整理electron 相关的项目问题,对自己来说也是温故知新,也希望能对小伙伴们有所帮助,大家共同努力共同进步。加油!!!! 虽然最近一年前端大环境不好,但是大家还是要加油鸭&#…

JavaScript 变量声明var、let、const

在 JavaScript 中,var、let和const是用于声明变量的关键字。 let和const是JavaScript里相对较新的变量声明方式。 let用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。 const声明一个只读的常量。一旦声明,常量的…