python-执行cmd指令(os.system和os.popen)

本文介绍如何使用Python的os模块调用CMD命令,包括os.system和os.popen的区别与应用。通过示例代码展示如何检测ADB连接的设备,适用于自动化测试和设备管理。

转载自:悠悠博客园

os.system

1.如果想在cmd执行python脚本,可以直接用如下指令

python [xx.py绝对路径]

比如我写了个hello.py的脚本,在脚本里面写入内容:print(“hello world!”),放到d盘目录路径为:d:\hello.py

2.os.system用来执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功

注意:os.system是简单粗暴的执行cmd指令,如果想获取在cmd输出的内容,是没办法获到的

os.popen

1.如果想获取控制台输出的内容,那就用os.popen的方法了,popen返回的是一个file对象,跟open打开文件一样操作了,r是以读的方式打开

# coding:utf-8

import os

# popen返回文件对象,跟open操作一样
f = os.popen(r"python d:\hello.py", "r")

d = f.read()  # 读文件
print(d)
print(type(d))
f.close()

2.执行结果:

注意:os.popen() 方法用于从一个命令打开一个管道。在Unix,Windows中有效

实例

1.前面对os.popen的方法有了初步了了解了,接下来就运用到实际操作中吧!

在app自动化的时候,经常用到指令:adb devices来判断是否连上了手机,那么问题来了,如何用python代码判断是否正常连上手机?

adb devices

2.代码参考:

# coding:utf-8
import os

# popen返回文件对象,跟open操作一样
f = os.popen(r"adb devices", "r")
shuchu = f.read()
f.close()

print(shuchu)  # cmd输出结果

# 输出结果字符串处理
s = shuchu.split("\n")   # 切割换行
new = [x for x in s if x != '']  # 去掉空''
print(new)

# 可能有多个手机设备
devices = []  # 获取设备名称
for i in new:
    dev = i.split('\tdevice')
    if len(dev)>=2:
        devices.append(dev[0])

if not devices:
    print("手机没连上")
else:
    print("当前手机设备:%s"%str(devices))

<think>我们正在比较Pythonos.system()os.popen()两个函数。这两个函数都用于执行系统命令,但有不同的行为用途。 注意:根据用户要求,我们将使用中文回答,并且对于数学表达式使用LaTeX格式(行内用$...$,独立公式用$$...$$)。同时,我们将生成相关问题。 引用说明:在回答中,我们可能会参考到之前关于subprocess的讨论,但这里主要聚焦于os模块的两个函数。 对比表: | 特性 | os.system() | os.popen() | |---------------------|------------------------------------------|---------------------------------------------| | **返回值** | 命令的退出状态码(整数) | 一个文件对象(用于读取命令输出) | | **输出处理** | 直接输出到控制台,不捕获输出 | 可以捕获命令的输出(通过文件对象读取) | | **阻塞行为** | 阻塞直到命令执行完成 | 同样阻塞直到命令执行完成(但可读取输出流) | | **使用场景** | 只需知道命令是否成功执行(状态码) | 需要获取命令输出的内容 | | **子进程管理** | 简单,无法与子进程交互 | 通过文件对象读取输出,但写入输入有限制 | | **安全性** | 与subprocess模块一样,有命令注入风险 | 同样有命令注入风险 | | **推荐程度** | 不推荐,已被subprocess模块替代 | 不推荐,已被subprocess模块替代 | 详细说明: 1. **os.system()** - 这个函数接收一个字符串命令,并在子shell中执行它。 - 它会阻塞当前进程,直到命令执行完成。 - 返回值是命令的退出状态码(0通常表示成功)。 - 命令的输出会直接打印到控制台,无法在程序中捕获。 - 示例: ```python import os status = os.system("ls -l") # 输出直接显示在控制台,status为退出状态码 if status == 0: print("命令执行成功") else: print("命令执行失败") ``` 2. **os.popen()** - 这个函数用于执行命令并捕获其输出(或提供输入)。 - 它返回一个文件对象,通过该对象可以读取命令的输出(如果模式为'r')或向命令写入输入(如果模式为'w')。 - 默认模式是读取('r')。 - 注意:os.popen()在命令执行完成后返回文件对象,因此它也是阻塞的。 - 示例(读取输出): ```python import os # 读取命令输出 output = os.popen("ls -l").read() print(output) # 输出命令执行结果 ``` - 示例(写入输入): ```python # 向命令写入(较少使用) with os.popen("grep 'error'", 'w') as f: f.write("error: file not found\n") ``` 重要提示: - 这两个函数在底层都是通过启动shell(在Unix上是`/bin/sh`,在Windows上是`cmd.exe`)来执行命令的,因此存在命令注入风险。如果命令字符串包含用户输入,务必小心。 - 在现代Python中,官方推荐使用`subprocess`模块来替代这两个函数,因为`subprocess`提供了更强大、更灵活且更安全的子进程管理功能。 与`subprocess`模块的对比: - `os.system()` 类似于 `subprocess.call()` 但不捕获输出。 - `os.popen()` 类似于 `subprocess.Popen()` 结合管道,但`subprocess.Popen`提供了更细粒度的控制(如分离标准输出标准错误,实时处理输出等)。 安全性警告:避免使用`shell=True`(在`subprocess`中)或直接传递字符串命令(在`os.system``os.popen`中)来处理不受信任的输入,以防止命令注入攻击。如果必须使用字符串命令,请确保对输入进行严格的转义。 示例:使用`subprocess`替代`os.popen()`来捕获输出: ```python import subprocess result = subprocess.run(["ls", "-l"], capture_output=True, text=True) print(result.stdout) ``` 因此,在新代码中,应优先考虑使用`subprocess`模块。 §§相关问题§§ 1. 如何用`subprocess`模块替代`os.system()`? 2. 在`subprocess`模块中如何同时捕获标准输出标准错误? 3. 如何防止在Python执行系统命令时的命令注入攻击? 4. `subprocess.Popen()`与`os.popen()`的主要区别是什么?</think>### Python `os.system()` vs `os.popen()` 功能对比 `os.system()` `os.popen()` 都是 Python 执行系统命令的传统方法,但它们在功能适用场景上有显著差异。以下是详细对比(推荐优先使用 `subprocess` 模块替代): | **特性** | `os.system()` | `os.popen()` | |----------------|----------------------------------------|-------------------------------------------| | **返回值** | 命令的退出状态码(整数) | 文件对象(用于读取命令输出) | | **输出处理** | 直接输出到控制台,**无法捕获** | 可捕获命令输出(通过文件对象读取) | | **阻塞行为** | 阻塞直到命令执行完成 | 阻塞直到命令执行完成 | | **使用场景** | 只需检查命令是否成功执行 | 需要获取命令输出的内容 | | **子进程管理** | 无直接控制能力 | 有限控制(通过文件对象) | | **安全性** | 有命令注入风险(尤其使用 `shell=True`)| 同左 | | **推荐程度** | ⚠️ 不推荐(已被 `subprocess` 替代) | ⚠️ 不推荐(已被 `subprocess` 替代) | --- ### 详细说明与示例 #### 1. **`os.system()` - 简单执行** ```python import os # 执行命令(直接输出到控制台) exit_code = os.system("ls -l") # Unix/Linux # exit_code = os.system("dir") # Windows # 检查执行结果(0表示成功) if exit_code == 0: print("命令执行成功") else: print(f"命令失败,错误码: {exit_code}") ``` - **适用场景**:仅需检查命令是否成功执行,无需捕获输出 - **缺点**: - 无法获取命令输出内容 - 跨平台兼容性差(Windows/Linux命令不同) - 安全风险:直接拼接命令字符串易受注入攻击[^1] #### 2. **`os.popen()` - 捕获输出** ```python import os # 捕获命令输出 output = os.popen("df -h").read() # 读取磁盘信息 print(f"磁盘使用情况:\n{output}") # 分块读取大输出 with os.popen("tail -f /var/log/syslog") as stream: while True: line = stream.readline() if not line: break if "ERROR" in line: alert_system(line) ``` - **适用场景**:需要获取命令输出的内容 - **模式选择**: - `os.popen(cmd, 'r')`:读取命令输出(默认) - `os.popen(cmd, 'w')`:向命令输入数据(较少用) - **缺点**: - 无法分离标准输出(stdout)错误输出(stderr) - 无法设置超时控制 - 资源管理需手动关闭文件对象 --- ### 与 `subprocess` 模块对比 **推荐优先使用 `subprocess.run()` 替代二者**: ```python import subprocess # 替代 os.system() result = subprocess.run(["ls", "-l"], check=True) # 替代 os.popen() result = subprocess.run(["df", "-h"], capture_output=True, text=True) print(result.stdout) ``` 优势: - 统一接口处理输入/输出/错误流 - 支持超时控制(`timeout=10`) - 避免命令注入(使用列表传参) - 跨平台行为一致 --- ### 安全警告 避免直接拼接用户输入的命令: ```python # 危险示例(命令注入风险) user_input = "malicious_file; rm -rf /" os.system(f"rm {user_input}") # 可能删除整个系统! # 安全做法(使用 subprocess + 列表传参) subprocess.run(["rm", user_input]) # 仅删除指定文件 ``` > **关键结论**:Python 3.5+ 应优先使用 `subprocess` 模块,`os.system()` `os.popen()` 仅用于遗留代码维护[^1]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值