8.5 os 模块


文章目录


前言

本文主要介绍OS模块的特点、常用函数、跨平台编程建议以及应用示例等知识点。


一、os 模块概述

os(Operating System)模块是 Python 的标准库之一,提供了丰富的方法来与操作系统进行交互。通过 os 模块,我们可以执行文件和目录操作、获取系统信息、管理进程等。

  1. 主要特点:
    跨平台兼容性:对于不同操作系统共有的功能使用相同接口
    可移植性:代码可以在不同操作系统间迁移
    扩展性:可以访问特定操作系统的扩展功能

二、常用函数详解

2.1 路径相关操作

获取当前工作目录

python 复制代码
python
import os

# 获取当前工作目录的绝对路径
current_path = os.getcwd()
print(f"当前工作目录: {current_path}")
print(f"目录类型: {type(current_path)}")

# 示例输出(Windows): C:\Users\Username\Projects
# 示例输出(Linux/Mac): /home/username/projects
列出目录内容
python
import os

# 列出指定目录下的所有文件和子目录
def list_directory_contents(path='.'):
    """列出目录内容"""
    try:
        contents = os.listdir(path)
        print(f"目录 '{path}' 的内容:")
        for i, item in enumerate(contents, 1):
            item_path = os.path.join(path, item)
            if os.path.isdir(item_path):
                print(f"  {i:2d}. [目录] {item}")
            else:
                print(f"  {i:2d}. [文件] {item} (大小: {os.path.getsize(item_path)} 字节)")
        return contents
    except FileNotFoundError:
        print(f"错误: 目录 '{path}' 不存在")
    except PermissionError:
        print(f"错误: 没有权限访问目录 '{path}'")
    return []

# 使用示例
list_directory_contents('.')  # 当前目录
# list_directory_contents('C:/')  # Windows根目录
# list_directory_contents('/')    # Linux/Mac根目录

2.2 路径处理函数

获取绝对路径

python 复制代码
python
import os

# 获取绝对路径示例
relative_path = './test.txt'
absolute_path = os.path.abspath(relative_path)
print(f"相对路径: {relative_path}")
print(f"绝对路径: {absolute_path}")

# 处理不同操作系统的路径
paths_to_test = [
    '.',                  # 当前目录
    '..',                 # 上级目录
    './subdir/file.txt',  # 子目录文件
    '~/Documents',        # 用户目录(Linux/Mac)
    'C:\\Users\\Test',    # Windows路径
]

print("\n不同路径的绝对路径转换:")
for path in paths_to_test:
    try:
        abs_path = os.path.abspath(path)
        print(f"  {path:<20} -> {abs_path}")
    except Exception as e:
        print(f"  {path:<20} -> 错误: {e}")
拆分和合并路径
python
import os

# 拆分路径
def split_path_demo(path):
    """展示路径拆分功能"""
    dir_name, file_name = os.path.split(path)
    print(f"原始路径: {path}")
    print(f"  目录部分: {dir_name}")
    print(f"  文件部分: {file_name}")
    print(f"  文件名(不含扩展名): {os.path.splitext(file_name)[0]}")
    print(f"  扩展名: {os.path.splitext(file_name)[1]}")
    return dir_name, file_name

# 测试不同路径
print("路径拆分示例:")
print("=" * 50)
split_path_demo('/home/user/documents/report.pdf')
split_path_demo('C:\\Program Files\\Python\\python.exe')
split_path_demo('relative/path/to/file.txt')

# 合并路径(跨平台安全)
print("\n" + "=" * 50)
print("路径合并示例:")

# 使用os.path.join确保路径分隔符正确
base_dir = '/home/user'
sub_dir = 'documents'
filename = 'report.txt'

full_path = os.path.join(base_dir, sub_dir, filename)
print(f"合并路径: {full_path}")

# 处理多个部分
parts = ['C:', 'Users', 'Test', 'Data', 'file.csv']
windows_path = os.path.join(*parts)
print(f"Windows风格路径: {windows_path}")

# 自动处理多余分隔符
path1 = '/home/user//documents/'
path2 = '/file.txt'
clean_path = os.path.join(path1, path2)
print(f"清理后的路径: {clean_path}")

2.3 文件信息获取

文件时间信息

python 复制代码
python
import os
import datetime
import time

def get_file_times(filepath):
    """获取文件的创建、修改、访问时间"""
    if not os.path.exists(filepath):
        print(f"文件 '{filepath}' 不存在")
        return
    
    print(f"\n文件 '{filepath}' 的时间信息:")
    print("-" * 40)
    
    try:
        # 创建时间(某些Unix系统可能返回修改时间)
        ctime = os.path.getctime(filepath)
        print(f"创建时间: {datetime.datetime.fromtimestamp(ctime)}")
        
        # 最后修改时间
        mtime = os.path.getmtime(filepath)
        print(f"修改时间: {datetime.datetime.fromtimestamp(mtime)}")
        
        # 最后访问时间
        atime = os.path.getatime(filepath)
        print(f"访问时间: {datetime.datetime.fromtimestamp(atime)}")
        
        # 格式化输出
        print(f"\n格式化时间:")
        print(f"创建: {time.ctime(ctime)}")
        print(f"修改: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(mtime))}")
        
    except OSError as e:
        print(f"获取时间信息失败: {e}")

# 使用示例
get_file_times(__file__)  # 当前文件
# get_file_times('C:/Windows/explorer.exe')  # Windows系统文件

文件和目录判断

python 复制代码
python
import os

def check_path_info(path):
    """检查路径信息"""
    print(f"\n检查路径: {path}")
    print("-" * 30)
    
    if os.path.exists(path):
        print(f"✓ 路径存在")
        
        if os.path.isdir(path):
            print(f"✓ 这是一个目录")
            size = os.path.getsize(path)
            print(f"  目录大小: {size} 字节 (通常为0或4096)")
            
        elif os.path.isfile(path):
            print(f"✓ 这是一个文件")
            size = os.path.getsize(path)
            print(f"  文件大小: {size} 字节 ({size/1024:.2f} KB)")
            
        elif os.path.islink(path):  # 检查是否是链接(Linux/Mac)
            print(f"✓ 这是一个符号链接")
            real_path = os.path.realpath(path)
            print(f"  真实路径: {real_path}")
            
        # 检查可访问性
        print(f"  可读: {os.access(path, os.R_OK)}")
        print(f"  可写: {os.access(path, os.W_OK)}")
        print(f"  可执行: {os.access(path, os.X_OK)}")
        
    else:
        print(f"✗ 路径不存在")
    
    # 额外信息
    print(f"\n路径详细信息:")
    print(f"  绝对路径: {os.path.abspath(path)}")
    print(f"  目录名: {os.path.dirname(path)}")
    print(f"  基名: {os.path.basename(path)}")

# 测试不同类型路径
paths_to_check = [
    '.',                      # 当前目录
    __file__,                 # 当前文件
    '/etc/passwd',            # Linux系统文件
    'C:/Windows/System32',    # Windows系统目录
    'nonexistent_file.txt',   # 不存在的文件
]

for path in paths_to_check:
    check_path_info(path)

2.4 目录操作

创建目录

python 复制代码
python
import os

def create_directory_demo():
    """创建目录演示"""
    print("目录创建演示")
    print("=" * 50)
    
    # 创建单个目录
    single_dir = 'test_single_dir'
    try:
        os.mkdir(single_dir)
        print(f"✓ 创建目录: {single_dir}")
    except FileExistsError:
        print(f"⚠ 目录已存在: {single_dir}")
    except PermissionError:
        print(f"✗ 权限不足,无法创建: {single_dir}")
    
    # 创建多级目录
    multi_dir = 'test_multi/dir1/dir2/dir3'
    try:
        os.makedirs(multi_dir, exist_ok=True)  # exist_ok=True表示目录存在时不报错
        print(f"✓ 创建多级目录: {multi_dir}")
    except Exception as e:
        print(f"✗ 创建失败: {e}")
    
    # 创建带权限的目录(Unix-like系统)
    secure_dir = 'secure_dir'
    try:
        os.makedirs(secure_dir, mode=0o755, exist_ok=True)
        print(f"✓ 创建带权限目录: {secure_dir}")
    except Exception as e:
        print(f"✗ 创建失败: {e}")
    
    # 验证创建结果
    print(f"\n验证创建的目录:")
    for root, dirs, files in os.walk('test_multi'):
        level = root.replace('test_multi', '').count(os.sep)
        indent = ' ' * 2 * level
        print(f"{indent}{os.path.basename(root)}/")

# 执行演示
create_directory_demo()
删除目录和文件
python
import os
import shutil  # 用于递归删除

def delete_operations_demo():
    """删除操作演示"""
    print("\n" + "=" * 50)
    print("删除操作演示")
    
    # 先创建一些测试文件和目录
    test_structure = {
        'to_delete.txt': '这是一个测试文件',
        'empty_dir': None,
        'dir_with_files': {
            'file1.txt': '文件1',
            'file2.txt': '文件2',
            'subdir': {
                'deep_file.txt': '深层文件'
            }
        }
    }
    
    def create_test_structure(base, structure):
        """创建测试目录结构"""
        for name, content in structure.items():
            path = os.path.join(base, name)
            if content is None:
                os.makedirs(path, exist_ok=True)
            elif isinstance(content, dict):
                os.makedirs(path, exist_ok=True)
                create_test_structure(path, content)
            else:
                os.makedirs(os.path.dirname(path), exist_ok=True)
                with open(path, 'w', encoding='utf-8') as f:
                    f.write(content)
    
    # 创建测试结构
    test_base = 'test_delete'
    create_test_structure(test_base, test_structure)
    print(f"✓ 创建测试结构: {test_base}")
    
    # 删除单个文件
    file_to_delete = os.path.join(test_base, 'to_delete.txt')
    try:
        os.remove(file_to_delete)
        print(f"✓ 删除文件: {file_to_delete}")
    except Exception as e:
        print(f"✗ 删除失败: {e}")
    
    # 删除空目录
    empty_dir = os.path.join(test_base, 'empty_dir')
    try:
        os.rmdir(empty_dir)
        print(f"✓ 删除空目录: {empty_dir}")
    except Exception as e:
        print(f"✗ 删除失败: {e}")
    
    # 删除非空目录(需要递归删除)
    dir_with_files = os.path.join(test_base, 'dir_with_files')
    try:
        shutil.rmtree(dir_with_files)
        print(f"✓ 递归删除目录: {dir_with_files}")
    except Exception as e:
        print(f"✗ 删除失败: {e}")
    
    # 清理剩余目录
    if os.path.exists(test_base):
        os.rmdir(test_base)
        print(f"✓ 清理测试目录: {test_base}")

# 执行演示
delete_operations_demo()

2.5 系统操作

更改工作目录

python 复制代码
python
import os

def change_directory_demo():
    """更改工作目录演示"""
    print("\n" + "=" * 50)
    print("更改工作目录演示")
    
    original_dir = os.getcwd()
    print(f"原始工作目录: {original_dir}")
    
    # 尝试更改目录
    target_dir = os.path.dirname(original_dir)  # 上级目录
    try:
        os.chdir(target_dir)
        print(f"✓ 更改到: {target_dir}")
        print(f"  当前目录: {os.getcwd()}")
        
        # 列出新目录内容
        print(f"  目录内容: {os.listdir('.')[:5]}")  # 显示前5个
    except Exception as e:
        print(f"✗ 更改失败: {e}")
    
    # 返回原始目录
    os.chdir(original_dir)
    print(f"✓ 返回原始目录: {original_dir}")

# 执行演示
change_directory_demo()
执行系统命令
python
import os
import sys

def system_command_demo():
    """执行系统命令演示"""
    print("\n" + "=" * 50)
    print("执行系统命令演示")
    
    # 获取平台信息
    platform = sys.platform
    print(f"当前平台: {platform}")
    
    # 根据平台选择合适的命令
    if platform.startswith('win'):
        commands = [
            'echo Hello Windows',
            'dir',          # 列出目录
            'ver',          # 查看Windows版本
        ]
    else:  # Unix-like系统
        commands = [
            'echo Hello Unix/Linux/Mac',
            'ls -la',       # 详细列出目录
            'uname -a',     # 查看系统信息
        ]
    
    # 执行命令
    for cmd in commands:
        print(f"\n执行命令: {cmd}")
        print("-" * 40)
        
        try:
            # 注意:os.system有安全隐患,生产环境建议使用subprocess模块
            return_code = os.system(cmd)
            print(f"返回码: {return_code}")
        except Exception as e:
            print(f"执行失败: {e}")
    
    # 更安全的替代方案:subprocess模块
    print("\n" + "=" * 50)
    print("使用subprocess模块(更安全的方式)")
    
    import subprocess
    
    # 获取命令输出
    try:
        result = subprocess.run(['python', '--version'], 
                               capture_output=True, 
                               text=True)
        print(f"Python版本: {result.stdout.strip()}")
    except Exception as e:
        print(f"获取Python版本失败: {e}")

# 执行演示
system_command_demo()

2.6 实用工具函数

python 复制代码
python
import os

def os_utility_functions():
    """OS模块实用工具函数演示"""
    print("\n" + "=" * 50)
    print("OS模块实用工具函数演示")
    
    # 环境变量操作
    print("\n1. 环境变量操作:")
    print(f"   当前用户: {os.environ.get('USERNAME', os.environ.get('USER', 'Unknown'))}")
    print(f"   系统路径: {os.environ.get('PATH', '')[:100]}...")  # 显示前100字符
    
    # 可以设置环境变量(只在当前进程有效)
    os.environ['MY_CUSTOM_VAR'] = 'Hello World'
    print(f"   自定义变量: {os.environ.get('MY_CUSTOM_VAR')}")
    
    # 系统信息
    print("\n2. 系统信息:")
    print(f"   操作系统: {os.name}")  # 'posix', 'nt', 'java'
    print(f"   路径分隔符: {repr(os.sep)}")
    print(f"   行分隔符: {repr(os.linesep)}")
    
    # 遍历目录(walk函数)
    print("\n3. 目录遍历示例:")
    
    # 创建测试目录结构
    test_walk_dir = 'test_walk_structure'
    test_structure = {
        'dir1': {
            'file1.txt': '',
            'dir1_1': {
                'file1_1.txt': ''
            }
        },
        'dir2': {
            'file2.txt': ''
        },
        'root_file.txt': ''
    }
    
    # 创建测试结构(简化版)
    os.makedirs(os.path.join(test_walk_dir, 'dir1', 'dir1_1'), exist_ok=True)
    os.makedirs(os.path.join(test_walk_dir, 'dir2'), exist_ok=True)
    open(os.path.join(test_walk_dir, 'root_file.txt'), 'w').close()
    open(os.path.join(test_walk_dir, 'dir1', 'file1.txt'), 'w').close()
    open(os.path.join(test_walk_dir, 'dir1', 'dir1_1', 'file1_1.txt'), 'w').close()
    open(os.path.join(test_walk_dir, 'dir2', 'file2.txt'), 'w').close()
    
    print(f"   遍历目录: {test_walk_dir}")
    for root, dirs, files in os.walk(test_walk_dir):
        level = root.replace(test_walk_dir, '').count(os.sep)
        indent = ' ' * 4 * level
        print(f"{indent}[{os.path.basename(root) or 'ROOT'}]")
        
        subindent = ' ' * 4 * (level + 1)
        for file in files:
            print(f"{subindent}📄 {file}")
    
    # 清理测试目录
    import shutil
    shutil.rmtree(test_walk_dir)
    
    # 获取CPU数量
    print(f"\n4. CPU信息:")
    print(f"   CPU核心数: {os.cpu_count()}")
    
    # 进程管理
    print(f"\n5. 进程信息:")
    print(f"   当前进程ID: {os.getpid()}")
    print(f"   父进程ID: {os.getppid()}")

# 执行演示
os_utility_functions()

三、跨平台编程建议

python 复制代码
python
import os
import sys

def cross_platform_tips():
    """跨平台编程建议"""
    print("\n" + "=" * 50)
    print("跨平台编程最佳实践")
    
    # 1. 始终使用os.path.join创建路径
    print("\n1. 使用os.path.join创建路径:")
    
    # 错误的方式
    bad_path_windows = 'C:\\Users\\Test\\file.txt'
    bad_path_unix = '/home/user/file.txt'
    
    # 正确的方式
    correct_path = os.path.join('home', 'user', 'docs', 'file.txt')
    print(f"   跨平台路径: {correct_path}")
    
    # 2. 检查路径分隔符
    print("\n2. 处理不同系统的路径分隔符:")
    if os.name == 'nt':  # Windows
        print(f"   Windows系统,使用反斜杠")
    else:  # Unix-like
        print(f"   Unix-like系统,使用正斜杠")
    
    # 3. 使用os.path处理路径
    print("\n3. 使用os.path函数处理路径:")
    test_path = '/usr/local/bin/python3'
    print(f"   目录名: {os.path.dirname(test_path)}")
    print(f"   文件名: {os.path.basename(test_path)}")
    print(f"   是否为绝对路径: {os.path.isabs(test_path)}")
    
    # 4. 处理特殊路径
    print("\n4. 处理特殊路径:")
    print(f"   家目录: {os.path.expanduser('~')}")
    print(f"   环境变量路径: {os.path.expandvars('$HOME' if os.name != 'nt' else '%USERPROFILE%')}")
    
    # 5. 文件权限处理
    print("\n5. 文件权限处理:")
    current_file = __file__
    print(f"   文件权限 (八进制): {oct(os.stat(current_file).st_mode)[-3:]}")
    
    # 6. 创建临时文件和目录
    print("\n6. 临时文件处理:")
    import tempfile
    
    # 创建临时文件
    with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp:
        tmp.write('临时文件内容')
        tmp_path = tmp.name
        print(f"   临时文件路径: {tmp_path}")
    
    # 使用后清理
    os.unlink(tmp_path)
    print(f"   已清理临时文件")

# 执行演示
cross_platform_tips()

四、完整示例:文件管理器

python 复制代码
python
import os
import datetime

class SimpleFileManager:
    """简单的文件管理器"""
    
    def __init__(self):
        self.current_dir = os.getcwd()
    
    def list_directory(self, path=None):
        """列出目录内容"""
        if path is None:
            path = self.current_dir
        
        try:
            items = os.listdir(path)
            print(f"\n目录: {path}")
            print("-" * 60)
            print(f"{'类型':<6} {'大小':<10} {'修改时间':<20} {'名称'}")
            print("-" * 60)
            
            for item in items:
                item_path = os.path.join(path, item)
                
                # 判断类型
                if os.path.isdir(item_path):
                    item_type = "目录"
                    size = self._get_dir_size(item_path)
                    size_str = f"{size}" if size > 0 else "-"
                else:
                    item_type = "文件"
                    size = os.path.getsize(item_path)
                    size_str = self._format_size(size)
                
                # 获取修改时间
                mtime = os.path.getmtime(item_path)
                mtime_str = datetime.datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
                
                print(f"{item_type:<6} {size_str:<10} {mtime_str:<20} {item}")
            
            print(f"\n总计: {len(items)} 个项目")
            
        except Exception as e:
            print(f"列出目录失败: {e}")
    
    def _get_dir_size(self, path):
        """获取目录大小(递归)"""
        total = 0
        for dirpath, dirnames, filenames in os.walk(path):
            for filename in filenames:
                filepath = os.path.join(dirpath, filename)
                try:
                    total += os.path.getsize(filepath)
                except OSError:
                    pass
        return total
    
    def _format_size(self, size):
        """格式化文件大小"""
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size < 1024.0 or unit == 'GB':
                break
            size /= 1024.0
        return f"{size:.1f} {unit}"
    
    def change_directory(self, path):
        """更改当前目录"""
        try:
            if os.path.isdir(path):
                os.chdir(path)
                self.current_dir = os.getcwd()
                print(f"当前目录已更改为: {self.current_dir}")
            else:
                print(f"路径不存在或不是目录: {path}")
        except Exception as e:
            print(f"更改目录失败: {e}")
    
    def show_info(self):
        """显示当前目录信息"""
        print(f"\n当前工作目录: {self.current_dir}")
        print(f"可用空间: {self._get_free_space()}")
    
    def _get_free_space(self):
        """获取磁盘可用空间"""
        try:
            stat = os.statvfs(self.current_dir) if hasattr(os, 'statvfs') else None
            if stat:
                free_space = stat.f_bavail * stat.f_frsize
                return self._format_size(free_space)
            return "未知"
        except:
            return "未知"
    
    def run(self):
        """运行文件管理器"""
        print("=" * 50)
        print("简单文件管理器")
        print("=" * 50)
        
        commands = {
            'ls': '列出目录内容',
            'cd': '更改目录 (cd <路径>)',
            'info': '显示当前目录信息',
            'exit': '退出'
        }
        
        while True:
            print(f"\n[{self.current_dir}]")
            cmd = input("> ").strip().split()
            
            if not cmd:
                continue
            
            command = cmd[0].lower()
            
            if command == 'exit':
                print("退出文件管理器")
                break
            elif command == 'ls':
                self.list_directory()
            elif command == 'cd':
                if len(cmd) > 1:
                    self.change_directory(cmd[1])
                else:
                    print("用法: cd <路径>")
            elif command == 'info':
                self.show_info()
            elif command == 'help':
                print("\n可用命令:")
                for cmd, desc in commands.items():
                    print(f"  {cmd:<8} - {desc}")
            else:
                print(f"未知命令: {command},输入 'help' 查看帮助")

# 使用示例
if __name__ == "__main__":
    # 创建并运行文件管理器
    fm = SimpleFileManager()
    # fm.run()  # 取消注释以交互式运行
    
    # 演示基本功能
    print("OS模块功能演示:")
    print("=" * 50)
    
    # 列出当前目录
    fm.list_directory()
    
    # 显示信息
    fm.show_info()
    
    # 测试目录操作
    test_dir = "test_os_demo"
    os.makedirs(test_dir, exist_ok=True)
    
    # 创建测试文件
    test_file = os.path.join(test_dir, "test.txt")
    with open(test_file, 'w') as f:
        f.write("OS模块测试文件")
    
    print(f"\n创建测试结构: {test_dir}")
    fm.list_directory(test_dir)
    
    # 清理
    import shutil
    shutil.rmtree(test_dir)
    print(f"\n已清理测试目录: {test_dir}")

通过掌握 os 模块的各种功能,你可以编写出强大且跨平台的 Python 程序,轻松处理文件和目录操作。


相关推荐
njsgcs7 小时前
blender内部python调用 cats-blender-plugin 导入模型
python·blender
郝学胜-神的一滴7 小时前
Python类型检查之isinstance与type:继承之辨与魔法之道
开发语言·数据结构·python·程序人生
DLite7 小时前
WSL中使用Mermaid离线生成LangGraph流程图
python·ai·流程图
天下·第二7 小时前
python - 【编译.py文件】部署运行
开发语言·python
还不秃顶的计科生7 小时前
力扣hot100第三题:最长连续序列python
python·算法·leetcode
linuxxx1107 小时前
request.build_absolute_uri()关于使用IP+端口
网络·python·网络协议·tcp/ip·django
linuxxx1108 小时前
request.build_absolute_uri()用法
python·django
玄同7658 小时前
我是如何学习编程的?——从 “扳手使用” 到编程学习:踩坑式实践的底层方法论
开发语言·人工智能·经验分享·笔记·python·学习·自然语言处理
Java后端的Ai之路8 小时前
【Python进阶学习】-NumPy详细介绍指南(附demo)
python·学习·numpy