判断subprocess调起的shell命令是否结束

本文介绍如何使用Python的subprocess库监测外部命令的执行状态。通过Popen类的poll方法可以有效判断命令是否完成,并据此执行回调操作。文章提供了一个使用logging模块记录执行时间的示例,展示了不同调用方式(shell=True与shell=False)的区别。
部署运行你感兴趣的模型镜像

前言

最近在使用subprocess遇到个问题,折腾了好半天才找到简单的解决办法,在这里记录下。

环境

Python:2.7.10
库:subprocess, logging

问题

使用subprocessPopen类来执行shell命令,要怎么样才能知道命令执行结束了,以此来执行回调方法。

解决办法

使用subprocess.Popen.poll方法来获取命令的执行情况。

poll方法的返回值有两种情况
  1. 当命令未运行结束的时候,返回None
  2. 当命令结束时,返回命令的返回值

演示

这里使用logging模块来辅助显示命令执行时间
logging模块设置

分别使用两种调用shell命令的方式来测试

  1. shell=True
    shell=True
  2. shell=False
    shell=False

完整演示
完整演示

您可能感兴趣的与本文相关的镜像

PyTorch 2.6

PyTorch 2.6

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>我们正在讨论如何使用Python的subprocess模块执行系统命令。根据用户要求,我们需要在回答中自然地添加引用标识,并且遵循特定的格式要求(如数学表达式格式、独立公式等)。同时,需要生成相关问题。回顾引用内容:引用[1]:介绍了subprocess模块的两种常用方法:`subprocess.run()`和`subprocess.Popen()`,并详细说明了`subprocess.run()`的参数。引用[2]:展示了使用`subprocess.Popen()`执行命令的示例,包括启动进程、获取PID以及杀死进程。引用[3]:提到了使用`subprocess.Popen()`调用系统命令的另一种形式。引用[4]:给出了一个封装了`subprocess.getstatusoutput()`的函数,用于执行命令并处理异常。根据用户问题,他想要了解如何使用subprocess模块执行系统命令的示例。因此,我们将提供几种常见的执行系统命令的方法,并给出示例代码。我们将按照以下步骤组织回答:1.介绍subprocess模块的基本使用场景。2.分别展示几种常用的方法,包括:a.使用`subprocess.run()`(推荐)b.使用`subprocess.getstatusoutput()`(简单命令)c.使用`subprocess.Popen()`(高级控制)3.每个方法都提供示例代码,并解释关键参数。4.讨论安全性问题(如shell=True的风险)。5.生成相关问题。注意:由于用户要求使用中文,并且行内数学表达式要使用$...$,独立公式用$$...$$,但在这个回答中可能数学公式较少,但若有则遵守规则。我们将按照要求添加引用标记,例如在提到subprocess.run()时引用[1],在Popen示例时引用[2][3]等。开始回答:</think> ### Python subprocess 模块执行系统命令详解 `subprocess` 模块允许 Python 程序执行系统命令并与其进行交互。以下是主要方法的使用示例: #### 1. `subprocess.run()` 方法(官方推荐) ```python import subprocess result = subprocess.run( ["ls", "-l"], # 命令参数列表 stdout=subprocess.PIPE, # 捕获标准输出 stderr=subprocess.PIPE, # 捕获错误输出 text=True, # 返回字符串而非字节 check=True # 非零退出码抛出异常 ) print("输出内容:", result.stdout) print("退出码:", result.returncode) ``` 特点: - 同步执行,等待命令完成 - 自动清理子进程资源 - 支持超时控制(`timeout=10`)[^1] #### 2. `subprocess.getstatusoutput()` 方法 ```python import subprocess exitcode, output = subprocess.getstatusoutput("pwd") if exitcode == 0: print(f"当前目录: {output}") else: print(f"命令执行失败: {output}") # 封装实用函数 def run_cmd(command): exitcode, output = subprocess.getstatusoutput(command) if exitcode != 0: raise Exception(output) return output print("磁盘使用情况:", run_cmd("df -h"))[^4] ``` #### 3. `subprocess.Popen()` 方法(高级控制) ```python from subprocess import Popen, PIPE import time # 启动后台进程 proc = Popen( ["ping", "example.com", "-c", "5"], stdout=PIPE, text=True ) print(f"进程PID: {proc.pid} - 启动时间: {time.ctime()}") # 监控进程状态 while proc.poll() is None: # 进程仍在运行 time.sleep(1) print("等待进程结束...") output = proc.stdout.read() print(f"命令输出:\n{output}")[^3] ``` #### 4. 带超时的进程控制 ```python try: result = subprocess.run( ["sleep", "30"], timeout=5, # 设置5秒超时 check=True ) except subprocess.TimeoutExpired: print("命令执行超时!") # 添加自定义处理逻辑 ``` ### 关键注意事项 1. **参数安全性** - 避免直接拼接用户输入:使用列表参数而非字符串 - 危险示例:`subprocess.run(f"rm {user_input}", shell=True)` ❌ - 安全做法:`subprocess.run(["rm", filename])` ✅ 2. **资源管理** - 使用 `with` 语句自动清理资源: ```python with Popen(["long_running_task"], stdout=PIPE) as proc: output = proc.communicate()[0] ``` 3. **跨平台兼容性** - Windows 使用 `dir` 替代 `ls` - 使用 `sys.platform` 判断操作系统: ```python cmd = ["dir"] if sys.platform == "win32" else ["ls", "-l"] ``` ### 安全最佳实践 ```python def safe_run(command_list): """安全执行命令的封装函数""" try: result = subprocess.run( command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=30, check=True ) return result.stdout except subprocess.CalledProcessError as e: return f"错误 {e.returncode}: {e.stderr}" except subprocess.TimeoutExpired: return "命令执行超时" ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值