Python执行命令的几种方式
各位小伙伴们,大家好呀!看看今天我又给各位带来了什么文章?本文标题是《Python执行系统命令的几种方法》,很明显是关于文章的文章哈哈哈,其中内容主要会涉及到等等,如果能帮到你,觉得很不错的话,欢迎各位多多点评和分享!
执行系统命令首选subprocess模块,因其功能全面、安全性高且支持精细控制;os.system()和os.popen()虽简单但功能有限,易引发安全风险,适用于简单场景;使用时需避免shell注入、注意编码和资源管理。

Python执行系统命令,在我看来,主要有那么几板斧:最直接的 os.system(),能获取输出的 os.popen(),以及现代Python里几乎是万金油的 subprocess 模块。要说哪种最好,那肯定首推 subprocess,它功能最全,控制力最强,也最符合当下编程的最佳实践。
解决方案
当我们需要在Python程序里调用外部命令时,选择哪种方式,其实是功能需求和便捷性之间的一个权衡。
1. os.system(command):最简单粗暴的选择
这个函数就是直接把你的字符串命令扔给操作系统的shell去执行。它会阻塞当前Python程序的执行,直到外部命令完成,然后返回命令的退出状态码(通常0表示成功,非0表示失败)。
import os
# 执行一个简单的命令
return_code = os.system("ls -l /tmp")
print(f"命令退出码: {return_code}")
# 执行一个不存在的命令
return_code_fail = os.system("non_existent_command")
print(f"失败命令退出码: {return_code_fail}")2. os.popen(command, mode='r', buffering=-1):需要获取输出时的旧方案
如果你不仅想执行命令,还想拿到命令的输出内容,os.popen() 就能派上用场。它会返回一个文件对象,你可以像读文件一样去读取命令的标准输出。
import os
# 获取命令输出
with os.popen("df -h") as f:
output = f.read()
print("磁盘使用情况:")
print(output)
# 也可以写入,但通常不这么用
# with os.popen("grep python", mode='w') as f:
# f.write("python is great\n")
# f.write("java is also great\n")3. subprocess 模块:现代Python的王道
这才是真正值得深入研究和广泛使用的模块。它提供了极高的灵活性,可以处理标准输入、输出、错误流,控制进程的生命周期,甚至是非阻塞地执行命令。subprocess 模块里有几个常用的函数:
*`subprocess.run(args, , stdin=None, input=None, capture_output=False, text=None, check=False, shell=False, timeout=None, encoding=None, errors=None, env=None, cwd=None, ...)
** 这是Python 3.5+ 推荐的、最通用的方式。它执行命令,等待其完成,并返回一个CompletedProcess` 对象,包含了退出码、标准输出和标准错误。import subprocess # 简单执行并捕获输出 result = subprocess.run(["ls", "-l", "/tmp"], capture_output=True, text=True) print("命令输出:") print(result.stdout) print("命令错误输出:") print(result.stderr) print(f"退出码: {result.returncode}") # 捕获输出并检查错误 (check=True 会在非零退出码时抛出 CalledProcessError) try: result_checked = subprocess.run( ["cat", "/non_existent_file"], capture_output=True, text=True, check=True ) print(result_checked.stdout) except subprocess.CalledProcessError as e: print(f"命令执行失败: {e.returncode}") print(f"错误信息: {e.stderr}") # 通过 shell=True 执行,但要小心安全问题 # result_shell = subprocess.run("echo $PATH", shell=True, capture_output=True, text=True) # print(f"PATH: {result_shell.stdout}")*`subprocess.call(args, , shell=False, ...)
** 功能上有点像os.system()`,返回退出状态码,但提供了更多控制选项。*`subprocess.check_call(args, , shell=False, ...)
** 与subprocess.call()类似,但如果命令返回非零退出码,会抛出CalledProcessError` 异常。*`subprocess.check_output(args, , shell=False, ...)
** 执行命令并返回其标准输出(以字节串形式),如果命令返回非零退出码,同样会抛出CalledProcessError`。*`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=(), , group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None)
** 这是subprocess模块中最底层的接口,提供了对子进程的完全控制。你可以用它来启动一个子进程,然后通过communicate()` 方法与它交互,或者等待它完成。这在需要更复杂交互(比如管道、异步执行)的场景下非常有用。import subprocess # 启动一个进程,但不立即等待其完成 process = subprocess.Popen(["ping", "-c", "4", "google.com"], stdout=subprocess.PIPE, text=True) # 可以做其他事情... print("后台pinging中...") # 等待进程完成并获取输出 stdout, stderr = process.communicate() print("Ping结果:") print(stdout) print(f"退出码: {process.returncode}")
os.system() 和 os.popen() 的使用场景与局限性是什么?
说实话,现在在新的Python项目里,我很少会主动去用 os.system() 或 os.popen() 了,除非是那种特别简单、对错误处理和输出解析要求不高的场景,或者为了兼容一些老旧代码。
os.system() 的优点是极其简洁,一行代码就能搞定。比如,你只是想触发一个外部脚本运行,根本不关心它的输出,也不需要复杂的错误判断,只要知道它有没有“崩”就行。这时候,os.system("my_script.sh") 确实是最快的。但它的局限性也很明显:它无法直接捕获命令的标准输出或标准错误,你只能通过返回值判断命令是否成功。如果命令执行失败,你拿不到具体的错误信息,这对于排查问题来说就很头疼。另外,它会阻塞当前进程,如果外部命令执行时间很长,你的Python程序就会一直卡在那里。
os.popen() 呢,比 os.system() 稍微好一点,因为它能让你读取命令的输出。这在一些需要获取外部命令结果的场景下还算实用。比如,你想快速获取一个 ls 或 df 命令的结果并做个简单的打印。但它的问题在于,它也只能读取标准输出,对标准错误流的处理就比较麻烦了。你很难区分哪部分是正常输出,哪部分是错误信息。而且,它同样是阻塞的,并且在错误处理方面依然不如 subprocess 那么精细。更重要的是,它返回的文件对象需要手动关闭,虽然 with 语句能帮忙,但总体上还是不如 subprocess 模块提供的 CompletedProcess 对象那样封装得好,功能也更单一。在我看来,这两个老伙计在功能上已经显得有些“力不从心”了。
为什么说 subprocess 模块是执行系统命令的最佳实践?
我觉得 subprocess 模块之所以能成为现代Python里执行系统命令的最佳实践,核心就在于它的强大、灵活和安全性。它不仅仅是执行命令,更像是提供了一个完整的“子进程管理中心”。
首先,全面的输入输出控制是它最大的亮点。你可以轻松地将命令的标准输出(stdout)、标准错误(stderr)重定向到管道(pipe)进行捕获,甚至可以将文件内容作为标准输入传递给子进程。这对于需要与外部程序进行复杂交互的场景(比如,运行一个命令行工具并传入大量参数,然后解析其返回的JSON或CSV数据)来说,简直是神来之笔。subprocess.run() 返回的 CompletedProcess 对象,直接把 stdout、stderr 和 returncode 都打包好了,一目了然。
其次,精细的错误处理是 subprocess 的另一大优势。通过 check=True 参数,你可以让Python在子进程返回非零退出码时自动抛出 CalledProcessError 异常,这样你就可以用标准的 try...except 结构来优雅地处理命令执行失败的情况,而不是仅仅拿到一个退出码然后自己去判断。这让程序的健壮性大大提高。
再者,安全性和灵活性也值得一提。当 shell=False(这也是默认值)时,subprocess 会直接执行你传入的命令列表,而不是通过shell。这意味着它不会对你的命令进行shell解析,从而有效避免了“shell注入”的安全风险。如果你确实需要shell的特性(比如管道 |、重定向 > 等),你可以明确设置 shell=True,但这时候你就需要确保你传入的命令字符串是安全的,或者至少是来自可信源的。此外,subprocess.Popen 提供了更底层的控制,你可以启动一个非阻塞的子进程,在后台运行它,同时你的Python程序可以继续做其他事情,这对于需要并发执行多个外部任务的场景非常有用。
总的来说,subprocess 模块的设计哲学就是“给你更多的控制权,让你能更安全、更灵活地与外部世界交互”。它解决了老旧方法在功能、安全和易用性上的诸多痛点,所以,只要不是那种“一锤子买卖”的简单执行,我都会毫不犹豫地选择 subprocess。
在 Python 中执行系统命令时,有哪些常见的陷阱和安全考量?
在Python里执行系统命令,虽然方便,但确实有一些坑,特别是安全方面的,稍不留神就可能踩进去。
一个最常见的陷阱就是shell注入。当你使用 subprocess.run(command_string, shell=True) 或者 os.system(command_string) 这种方式,并且 command_string 是由用户输入或外部数据拼接而成时,就可能发生。比如,你期望执行 rm -rf /tmp/user_data,但如果用户输入了 user_data; rm -rf /,那么你的程序在 shell=True 的情况下,就可能把整个根目录都删掉。这是非常危险的。
# 这是一个非常危险的例子,切勿在生产环境使用!
user_input = "my_file; echo '恶意代码被执行了!'"
# subprocess.run(f"echo {user_input}", shell=True) # 危险!正确的做法是尽量避免使用 shell=True,而是将命令和参数以列表的形式传递给 subprocess.run() 或 subprocess.Popen()。这样,Python会直接执行命令,不会通过shell进行解析,用户输入的数据会被当作普通参数传递,而不是命令的一部分。
# 安全的做法 user_input = "my_file; echo '恶意代码被执行了!'" subprocess.run(["echo", user_input]) # 这里的 user_input 只是一个参数,不会被执行
另一个需要注意的点是编码问题。特别是在Windows系统上,或者处理一些非UTF-8编码的输出时,subprocess 捕获到的字节串可能会导致乱码。这时候,subprocess.run() 的 text=True 参数(或 Python 3.7+ 的 encoding 参数)就显得尤为重要,它能帮你自动解码。如果自动解码不行,你就需要手动指定 encoding='gbk' 或其他适合的编码。
阻塞与非阻塞也是一个考量。os.system()、os.popen() 以及 subprocess.run()、subprocess.call()、subprocess.check_call()、subprocess.check_output() 默认都是阻塞的,意味着你的Python程序会等待外部命令执行完毕。如果外部命令需要很长时间,你的程序就会“假死”。这时候,subprocess.Popen 就派上用场了,它可以让你启动一个子进程,然后你的Python程序可以继续执行其他任务,需要时再回来检查子进程的状态或获取其输出。
最后,资源管理。如果你用 subprocess.Popen 启动了子进程,并且重定向了标准输入/输出/错误,记得在不再需要时调用 process.wait() 等待子进程结束,或者在适当的时候清理资源,比如关闭文件描述符。虽然Python的垃圾回收机制通常会处理这些,但显式地管理总归是更稳妥的做法。
总之,执行系统命令是把双刃剑,它赋予了Python强大的能力,但也带来了潜在的风险。理解这些陷阱并采取正确的预防措施,才能让你的代码既强大又安全。
以上就是《Python执行命令的几种方式》的详细内容,更多关于的资料请关注golang学习网公众号!
Golang数组长度与容量解析
- 上一篇
- Golang数组长度与容量解析
- 下一篇
- PHP权限继承与角色设计详解
-
- 文章 · python教程 | 2小时前 |
- PandasDataFrame列赋值NaN方法解析
- 205浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python元组括号用法与列表推导注意事项
- 143浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- ib\_insync获取SPX历史数据教程
- 395浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- GTK3Python动态CSS管理技巧分享
- 391浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python微服务开发:Nameko框架全解析
- 269浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Xarray重采样技巧:解决维度冲突方法
- 410浏览 收藏
-
- 文章 · python教程 | 3小时前 | 多进程编程 进程间通信 进程池 process multiprocessing
- Python3多进程技巧与实战指南
- 131浏览 收藏
-
- 文章 · python教程 | 4小时前 |
- Python列表线程传递方法详解
- 382浏览 收藏
-
- 文章 · python教程 | 5小时前 |
- Python国内镜像源设置方法
- 154浏览 收藏
-
- 文章 · python教程 | 5小时前 |
- 数据库迁移步骤与实用技巧分享
- 251浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3163次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3375次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3403次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4506次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3784次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

