玩转Python标准库:os与sys常用方法
目录
2.4 执行系统命令:os.system vs subprocess
3.4 标准输入输出错误:sys.stdin/stdout/stderr
从文件操作到命令行参数,一篇文章吃透Python最核心的两大系统模块。
一、os与sys:Python与操作系统之间的翻译官
在Python编程中,如果你想和操作系统底层打交道(比如读写文件、运行系统命令、获取环境变量),或者想控制Python解释器本身(比如接收命令行参数、修改模块搜索路径、退出程序),那么 os 和 sys 就是最核心的两个标准库。
os:负责操作系统相关功能(Operating System)
sys:负责解释器系统相关功能(System)
很多初学者分不清两者的区别,其实一句话:os管外面(操作系统),sys管里面(Python解释器)。
二、os模块:文件系统与进程管理
2.1 获取当前工作目录与路径拼接
python
import os
# 获取当前工作目录(类似 pwd / cd)
cwd = os.getcwd()
print(f"当前目录:{cwd}")
# 改变工作目录
os.chdir('/tmp')
print(os.getcwd())
# 跨平台路径拼接(推荐!)
path = os.path.join('folder', 'sub', 'file.txt')
print(path) # folder/sub/file.txt (Linux) 或 folder\sub\file.txt (Windows)
注意:不要手动拼 '/' 或 '\',用 os.path.join 自动适配操作系统。
2.2 创建、删除、重命名文件和目录
python
# 创建单级目录
os.mkdir('test_dir')
# 创建多级目录(相当于 mkdir -p)
os.makedirs('level1/level2/level3')
# 删除空目录
os.rmdir('test_dir') # 只能删空目录
os.removedirs('level1/level2/level3') # 递归删除空目录链
# 删除文件
os.remove('some_file.txt')
# 重命名文件或目录
os.rename('old_name.txt', 'new_name.txt')
2.3 遍历目录:os.walk
os.walk 是递归遍历目录树的利器:
python
for root, dirs, files in os.walk('my_folder'):
print(f"当前目录:{root}")
print(f"子目录:{dirs}")
print(f"文件:{files}")
# 可以动态修改 dirs 列表来控制遍历哪些子目录
实战:找出所有 .py 文件
python
py_files = []
for root, dirs, files in os.walk('.'):
for file in files:
if file.endswith('.py'):
py_files.append(os.path.join(root, file))
print(py_files)
2.4 执行系统命令:os.system vs subprocess
python
# 旧方法:os.system(不推荐,因为无法获取输出)
os.system('ls -l')
# 推荐:subprocess 模块(Python 3 更安全)
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
虽然 os.system 简单,但建议用 subprocess,因为它能更好地控制输入输出和错误处理。
2.5 环境变量操作
python
# 获取某个环境变量
path = os.environ.get('PATH')
print(path)
# 设置环境变量(仅当前进程生效)
os.environ['MY_VAR'] = 'hello'
print(os.environ['MY_VAR'])
# 判断环境变量是否存在
if 'JAVA_HOME' in os.environ:
print(os.environ['JAVA_HOME'])
三、sys模块:Python解释器“遥控器”
3.1 命令行参数:sys.argv
当你运行 python script.py arg1 arg2 -v 时,sys.argv 会捕获所有参数:
python
import sys
# sys.argv[0] 是脚本名称,后面依次是传入的参数
print(f"脚本名:{sys.argv[0]}")
print(f"参数个数:{len(sys.argv) - 1}")
for i, arg in enumerate(sys.argv[1:], 1):
print(f"参数{i}: {arg}")
# 运行示例:
python test.py hello world --debug
# 输出:
# 脚本名:test.py
# 参数个数:3
# 参数1: hello
# 参数2: world
# 参数3: --debug
3.2 程序退出:sys.exit
在脚本中遇到错误或希望提前终止时,使用 sys.exit() 返回退出码:
python
import sys
def main():
if not some_condition:
print("条件不满足,退出程序")
sys.exit(1) # 非0表示异常退出
# 正常逻辑
sys.exit(0) # 0表示成功
if __name__ == '__main__':
main()
3.3 路径相关:sys.path
sys.path 是Python搜索模块的路径列表,你可以动态添加自定义路径:
python
import sys
# 查看当前模块搜索路径
for p in sys.path:
print(p)
# 添加一个自定义目录,让Python能导入其中的模块
sys.path.append('/my/custom/module/folder')
常用于解决相对导入问题,或者临时加载未安装的本地包。
3.4 标准输入输出错误:sys.stdin/stdout/stderr
python
import sys
# 从标准输入读取一行(类似 input())
data = sys.stdin.readline().strip()
# 输出到标准输出
sys.stdout.write("Hello, world!\n")
# 输出错误信息(不会重定向到普通输出)
sys.stderr.write("Something went wrong!\n")
重定向示例(比如将输出同时写入文件):
python
original_stdout = sys.stdout
with open('log.txt', 'w') as f:
sys.stdout = f
print("这一行会写入文件,而不是屏幕")
sys.stdout = original_stdout
3.5 查看版本与平台信息
python
import sys
print(f"Python版本:{sys.version}")
print(f"版本详细信息:{sys.version_info}")
print(f"操作系统平台:{sys.platform}") # 'win32', 'linux', 'darwin' 等
可以用 sys.platform 来判断操作系统,实现跨平台兼容代码。
四、os vs sys:一张表看懂区别
| 功能领域 | os 模块 | sys 模块 |
| 文件和目录操作 | os.mkdir, os.remove, os.lk | wu |
| 环境变量 | os.environ | ❌ |
| 执行系统命令 | os.system | ❌ |
| 命令行参数 | ❌ | sys.argv |
| 退出程序 | ❌ | sys.exit |
| 模块搜索路径 | ❌ | sys.path |
| 标准输入/输出/错误 | ❌ | sys.stdin/stdout/stderr |
| Python解释器信息 | ❌ | sys.version, sys.platform |
简单记忆:os 是操作系统的手,sys 是 Python 解释器的脑。
五、实战案例:用os+sys打造一个命令行工具箱
让我们综合运用 os 和 sys,写一个可以统计目录下所有文件行数的小工具:
python
import os
import sys
def count_lines(file_path):
"""返回文件的行数"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return sum(1 for _ in f)
except Exception as e:
print(f"读取文件 {file_path} 出错: {e}", file=sys.stderr)
return 0
def main():
if len(sys.argv) != 2:
print("用法: python line_counter.py <目录路径>")
sys.exit(1)
target_dir = sys.argv[1]
if not os.path.isdir(target_dir):
print(f"错误: {target_dir} 不是一个有效目录", file=sys.stderr)
sys.exit(1)
total_lines = 0
file_count = 0
for root, dirs, files in os.walk(target_dir):
for file in files:
if file.endswith('.py'): # 只统计 Python 文件
full_path = os.path.join(root, file)
lines = count_lines(full_path)
total_lines += lines
file_count += 1
print(f"{full_path}: {lines} 行")
print(f"\n总计 {file_count} 个 Python 文件,共 {total_lines} 行代码")
if __name__ == '__main__':
main()
# 运行:
python line_counter.py ./my_project
这个小工具展示了:sys.argv 接收命令行参数、sys.exit 退出并返回错误码、sys.stderr 输出错误信息、os.walk 遍历目录、os.path.isdir / os.path.join 路径操作
六、避坑指南与进阶技巧
问题1:os.path.join 在 Windows 上路径分隔符是反斜杠,但Python字符串中反斜杠是转义符
解决:使用原始字符串或双反斜杠,但通常 os.path.join 返回的路径可以直接使用,Python会自动处理。
问题2:os.system 执行命令有安全风险(命令注入)
解决:使用 subprocess.run 并传递列表参数,而不是字符串。
问题3:修改 sys.path 后导入的模块可能与预期不符
解决:尽量用 PYTHONPATH 环境变量,或使用 pip install -e . 安装开发模式包。
进阶技巧
1. 获取脚本所在目录(无论从哪里调用):
script_dir = os.path.dirname(os.path.abspath(__file__))
2. 跨平台判断操作系统:
python
if sys.platform == 'win32':
# Windows 特定逻辑
elif sys.platform == 'linux':
# Linux 逻辑
3. 优雅地处理相对/绝对路径:
abs_path = os.path.abspath('data/config.json')
4. 使用 pathlib 替代部分 os.path(Python 3.4+ 推荐):
from pathlib import Path
p = Path('.') / 'data' / 'config.json'
print(p.resolve()) # 绝对路径
七、总结
| 模块 | 最常用的5个方法 |
| os | os.getcwd(), os.path.join(), os.walk(), os.environ, os.makedirs() |
| sys | sys.argv, sys.exit(), sys.path, sys.stdout.write(), sys.version |
更多推荐


所有评论(0)