个人总结
command.py
file.py
time.py
excel.py
with 的原理和用法
subprocess 模块
cline 提示词
PathLike
pathlib
peewee
生成随机ID
FastApi 使用 peewee
http connect
Dataframe Protocol
pyarrow
overload 函数重载
1111
peewee 线程安全
Python 日志模块
rabbitmq 问答
多进程 daemon 参数
记录异常
dict.py
多进程
忽略异常
timer.py
Ctrl+C 退出while
发布pip包
Bolo组件
迭代器与生成器
dataclass
单例模式(二)
单例模式(一)
errors.py
enum.py
每日学习
本文档使用 MrDoc 发布
-
+
首页
subprocess 模块
### 0. 概述 `subprocess` 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。 `subprocess` 模块首先推荐使用的是它的 run 方法,更高级的用法可以直接使用 Popen 方法。 > **subprocess 和 multiprocessing 的区别** > `subprocess` 用于启动外部的二进程程序; > `multiprocessing` 使用当前程序的函数来创建新的进程; #### 1. `subprocess.run()` 方法 该方法是 `Python3.5`新增的,用于可以接受等待进程执行结束后获取返回值的场景,如果可以满足使用需求,官方推荐使用该方法。 **该方法的执行过程是同步的**,脚本执行结束之前是阻塞的,只有脚本结束之后才会返回 `subprocess.CompletedProcess` 对象。 ``` class Command(object): def __init__(self, cmd): self.cmd = [cmd] def __call__(self, *args, **kwargs) -> subprocess.CompletedProcess: if len(args) == 1 and isinstance(args[0], (list, tuple)): self.cmd_line = " ".join(self.cmd + list(args[0])) else: self.cmd_line = " ".join(self.cmd + list(args)) logger.info("command = ", self.cmd_line) process = subprocess.run( self.cmd_line, shell=True, cwd=kwargs.get("cwd"), # stdout=subprocess.PIPE, # stderr=subprocess.STDOUT, capture_output=True, text=True) logger.info("command stdout", process.stdout) if not process.returncode: logger.info("command success") else: logger.error(f"command failed, error_info: {process.stderr}") return process python_cmd = Command("python") ``` #### 2. `subprocess.Popen()` 方法 该方法是 subprocess 的核心,子进程的创建和管理都靠它处理。Popen() 相当于 run() 的高级版本,更加灵活,使开发人员能够处理 run() 方法未涵盖的更丰富的场景。**该方法是异步的**,进程启动以后,我们可以通过预先指定好的 `stdout` 和 `stderr` 来实时读取到子进程的输出。 ``` # subprocess.Popen() 常用参数介绍: args:可以是字符串或者列表类型; stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄; shell:如果该参数为 True,将通过 shell 子进程来执行指定的命令; # Popen 返回的对象常用方法: poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None,项目中通过该方法返回判断进程是否执行结束。 wait(timeout): 等待子进程终止,如果进程执行时间较长,可以使用该方法来保证进程执行完整。 communicate(input,timeout): 和子进程交互,发送和读取数据。 send_signal(singnal): 发送信号到子进程 。 terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。 kill(): 杀死子进程。发送 SIGKILL 信号到子进程。 ``` #### 3. args参数 `args`参数可以是字符串,也可以是列表,来看两个示例: ``` subprocess.Popen(["cat","test.txt"]) subprocess.Popen("cat test.txt") ``` 在上面两个示例中,第二个不会被执行,因为默认情况下`shell=False`,如果args是字符串,必须是一个可执行文件的路径。 一般情况下args都是一个列表,因为是字符串的时候就不能传递参数了。当args是一个列表时,列表中的第一个元素会被当做可执行文件,列表中的其他项会被拼接成一个字符串作为可执行文件的参数; 当`shell=True`时情况则完全不同,此时上面两行代码都是可以执行的,如果args是一个列表,也会被拼接成字符串,然后将字符串传递给shell进程来执行; > 设置`shell=True`时,Popen()会在命令前面添加`/bin/sh -c`,完整的命令类似于:/bin/sh -c cat test.txt #### 3. shell参数 - `shell=True` 会创建一个shell进程,由shell进程创建子进程来执行我们的程序。当我们终止子进程的时候,其实终止的是shell进程,所以需要借助`psutil` 来获取到所有的子进程然后全部终止掉。 - `shell=False` 不会创建shell进程, 对于命令`cmd = "cat test.txt; rm test.txt" `: - 设置`shell=True`,会执行两条命令`cat`和`rm`; - 设置`shell=False`,会当成一条命令,只有`cat`被执行,后面都会被认为是`cat`的参数; - 设置`shell=False` 更安全,这样可以防止参数中有不安全的因素,比如说,如果参数是由前端用户传过来的,就很有可能被一些攻击人员输入不安全的代码; #### 4. run 与 Popen 的同步/异步对比实验   从执行结果可以看出,Popen 在子进程执行过程中就可以获取到日志,run 需要等待进程执行完成才能获取到日志。 如果需要执行的命令耗时很短,可以选择 run 方法;如果我们的数据构造流程通常比较长,需要实时获取日志,所以选择了 Popen。 #### 5. 参考 [Python subprocess 模块项目实战](https://testerhome.com/articles/33126)
gaojian
2024年9月12日 10:23
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码