0

0

python怎么执行系统命令_python执行系统命令方法汇总

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-09-13 12:40:02

|

969人浏览过

|

来源于php中文网

原创

执行系统命令首选subprocess模块,因其功能全面、安全性高且支持精细控制;os.system()和os.popen()虽简单但功能有限,易引发安全风险,适用于简单场景;使用时需避免shell注入、注意编码和资源管理。

python怎么执行系统命令_python执行系统命令方法汇总

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()`,返回退出状态码,但提供了更多控制选项。

    立即学习Python免费学习笔记(深入)”;

  • *`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里执行系统命令的最佳实践,核心就在于它的强大、灵活和安全性。它不仅仅是执行命令,更像是提供了一个完整的“子进程管理中心”。

Face Swap Online
Face Swap Online

在线免费换脸,支持图片换脸和视频换脸

下载

首先,全面的输入输出控制是它最大的亮点。你可以轻松地将命令的标准输出(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强大的能力,但也带来了潜在的风险。理解这些陷阱并采取正确的预防措施,才能让你的代码既强大又安全。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

425

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

537

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

313

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

78

2025.09.10

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

361

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1505

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

625

2023.11.24

AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

89

2026.02.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.8万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号