Python os模块详解

1. 概述

os模块是Python中用于与操作系统进行交互的核心模块,它提供了一系列函数,允许Python程序执行各种操作系统相关的任务,如:

  • 文件和目录操作(创建、删除、重命名、遍历等)
  • 进程管理(启动新进程、获取进程ID等)
  • 环境变量管理
  • 路径操作
  • 系统信息获取
  • 权限管理

os模块是Python标准库的一部分,无需安装即可使用。它提供了跨平台的API,使得相同的代码可以在不同的操作系统(如Windows、Linux、macOS)上运行,同时也允许访问特定于平台的功能。

2. 导入方式

要使用os模块,只需简单地导入即可:

import os

# 或者导入特定的函数
from os import mkdir, rmdir, rename

对于路径操作,通常会同时导入os.path子模块,它提供了专门用于路径处理的函数:

import os
import os.path

# 或者更简洁的方式
from os import path

3. 核心功能分类

3.1 文件和目录操作

3.1.1 文件操作

创建文件

# 创建空文件
def create_empty_file(filename):
    open(filename, 'a').close()

create_empty_file("empty.txt")

# 使用os模块创建文件(实际上os模块没有直接创建文件的函数)
# 但可以通过open函数或os.system调用系统命令
os.system("echo '' > newfile.txt")  # Windows和Linux都可用

删除文件

# 删除单个文件
os.remove("file.txt")

# 删除多个文件(需要异常处理)
files_to_delete = ["file1.txt", "file2.txt", "file3.txt"]
for file in files_to_delete:
    try:
        os.remove(file)
        print(f"已删除文件: {file}")
    except FileNotFoundError:
        print(f"文件不存在: {file}")
    except PermissionError:
        print(f"没有权限删除: {file}")

# 删除只读文件(Windows需要先修改权限)
if os.name == 'nt':  # Windows
    os.system("attrib -r read-only.txt")  # 移除只读属性
    os.remove("read-only.txt")

重命名文件

# 重命名文件
os.rename("old_name.txt", "new_name.txt")

# 移动文件(与重命名类似)
os.rename("source/file.txt", "destination/file.txt")

# 使用os.replace(更安全,会覆盖目标文件)
os.replace("old.txt", "new.txt")

复制文件

# os模块本身没有直接复制文件的函数,需要使用shutil模块
import shutil

shutil.copy("source.txt", "destination.txt")  # 复制文件内容和权限
shutil.copy2("source.txt", "destination.txt")  # 复制文件内容、权限和元数据

文件属性

# 获取文件大小(字节)
size = os.path.getsize("file.txt")
print(f"文件大小: {size} 字节")

# 获取文件创建时间、修改时间、访问时间
import datetime

mtime = os.path.getmtime("file.txt")  # 修改时间
time_str = datetime.datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
print(f"文件修改时间: {time_str}")

ctime = os.path.getctime("file.txt")  # 创建时间(Windows)或元数据修改时间(Unix)
atime = os.path.getatime("file.txt")  # 访问时间

# 检查文件是否存在
if os.path.exists("file.txt"):
    print("文件存在")

# 检查是否为文件
if os.path.isfile("file.txt"):
    print("这是一个文件")

3.1.2 目录操作

创建目录

# 创建单个目录
os.mkdir("new_dir")

# 创建多级目录
os.makedirs("parent/child/grandchild", exist_ok=True)
# exist_ok=True参数:如果目录已存在,不会抛出异常

删除目录

# 删除空目录
os.rmdir("empty_dir")

# 删除多级目录(需要确保目录为空)
os.removedirs("parent/child/grandchild")
# removedirs会尝试递归删除目录,只有当所有父目录都是空的时才会删除

# 删除非空目录(需要使用shutil模块)
import shutil
shutil.rmtree("non_empty_dir")  # 危险操作,谨慎使用

重命名目录

# 重命名目录
os.rename("old_dir", "new_dir")

# 移动目录
os.rename("source/dir", "destination/dir")

目录内容

# 列出目录内容
contents = os.listdir(".")
print("当前目录内容:", contents)

# 列出目录内容(包含详细信息)
for item in contents:
    item_path = os.path.join(".", item)
    if os.path.isfile(item_path):
        print(f"文件: {item} (大小: {os.path.getsize(item_path)} 字节)")
    elif os.path.isdir(item_path):
        print(f"目录: {item}")

遍历目录

# 递归遍历目录(os.walk)
for root, dirs, files in os.walk("."):
    print(f"当前目录: {root}")
    print(f"子目录: {dirs}")
    print(f"文件: {files}")
    print("---")

# 使用os.scandir(更高效)
with os.scandir(".") as entries:
    for entry in entries:
        if entry.is_file():
            print(f"文件: {entry.name}")
        elif entry.is_dir():
            print(f"目录: {entry.name}")

当前工作目录

# 获取当前工作目录
cwd = os.getcwd()
print(f"当前工作目录: {cwd}")

# 改变当前工作目录
os.chdir("/path/to/new/directory")
print(f"新的工作目录: {os.getcwd()}")

# 切换回原工作目录
os.chdir(cwd)

3.2 路径操作

os模块提供了丰富的路径操作功能,主要通过os.path子模块实现:

路径拼接

# 使用os.path.join拼接路径(推荐,会自动处理路径分隔符)
path1 = os.path.join("parent", "child", "file.txt")
print(path1)  # parent/child/file.txt (Linux/macOS) 或 parent\child\file.txt (Windows)

# 直接拼接(不推荐,跨平台问题)
path2 = "parent" + "/" + "child" + "/" + "file.txt"  # 在Windows上会有问题

路径拆分

# 拆分路径为目录名和文件名
full_path = "/home/user/documents/file.txt"
dir_name, file_name = os.path.split(full_path)
print(f"目录名: {dir_name}")  # /home/user/documents
print(f"文件名: {file_name}")  # file.txt

# 拆分路径为驱动器和路径(Windows特有)
if os.name == 'nt':
    drive, path = os.path.splitdrive("C:\\Users\\user\\file.txt")
    print(f"驱动器: {drive}")  # C:
    print(f"路径: {path}")  # \Users\user\file.txt

# 获取文件扩展名
base_name, extension = os.path.splitext("file.txt")
print(f"基本名称: {base_name}")  # file
print(f"扩展名: {extension}")  # .txt

路径规范化

# 规范化路径(处理..和.)
path = "/home/user/../documents/./file.txt"
normalized_path = os.path.normpath(path)
print(normalized_path)  # /home/documents/file.txt

# 获取绝对路径
relative_path = "../documents/file.txt"
absolute_path = os.path.abspath(relative_path)
print(absolute_path)  # /home/documents/file.txt

# 检查路径是否为绝对路径
print(os.path.isabs("/home/user/file.txt"))  # True
print(os.path.isabs("../file.txt"))  # False

路径检查

# 检查路径是否存在
print(os.path.exists("/home/user/file.txt"))

# 检查是否为文件
print(os.path.isfile("/home/user/file.txt"))

# 检查是否为目录
print(os.path.isdir("/home/user/documents"))

# 检查是否为符号链接
print(os.path.islink("/home/user/link.txt"))

# 检查是否为挂载点
print(os.path.ismount("/"))  # Linux/macOS

3.3 进程管理

3.3.1 执行系统命令

# 使用os.system执行系统命令
os.system("dir")  # Windows列出目录
os.system("ls -la")  # Linux/macOS列出目录

# 执行命令并获取返回值
result = os.system("echo 'Hello World'")
print(f"命令返回值: {result}")  # 0表示成功

# 使用os.popen执行命令并获取输出
output = os.popen("whoami").read()
print(f"当前用户: {output.strip()}")

# 更强大的 subprocess 模块(推荐用于复杂命令)
import subprocess
result = subprocess.run(["ls", "-la"], capture_output=True, text=True)
print(result.stdout)

3.3.2 进程信息

# 获取当前进程ID
pid = os.getpid()
print(f"当前进程ID: {pid}")

# 获取父进程ID
ppid = os.getppid()
print(f"父进程ID: {ppid}")

# 终止进程(不推荐,使用subprocess更好)
os.kill(pid, signal.SIGTERM)  # 需要导入signal模块

3.3.3 环境变量

# 获取所有环境变量
env_vars = os.environ
print("所有环境变量:", env_vars)

# 获取特定环境变量
path = os.environ.get("PATH")
home = os.environ.get("HOME")  # Linux/macOS
user_profile = os.environ.get("USERPROFILE")  # Windows

print(f"PATH: {path}")
print(f"HOME: {home}")
print(f"USERPROFILE: {user_profile}")

# 设置环境变量
os.environ["NEW_VAR"] = "new_value"
print(f"NEW_VAR: {os.environ.get('NEW_VAR')}")

# 删除环境变量
del os.environ["NEW_VAR"]
print(f"NEW_VAR是否存在: {'NEW_VAR' in os.environ}")

3.4 系统信息

# 获取操作系统名称
os_name = os.name
print(f"操作系统名称: {os_name}")  # 'nt'表示Windows, 'posix'表示Linux/macOS

# 获取详细的系统信息
if os_name == 'nt':
    # Windows
    print(f"Windows版本: {os.sys.getwindowsversion()}")
else:
    # Linux/macOS
    print(f"Unix版本: {os.uname()}")

# 获取登录用户
if os_name == 'nt':
    print(f"当前用户: {os.getlogin()}")
else:
    print(f"当前用户: {os.getlogin()}")

# 获取系统的换行符
print(f"系统换行符: {repr(os.linesep)}")

# 获取路径分隔符
print(f"路径分隔符: {os.sep}")

# 获取环境变量分隔符
print(f"环境变量分隔符: {os.pathsep}")

3.5 权限管理

# 获取文件权限(Linux/macOS)
if os.name != 'nt':
    import stat
    file_stats = os.stat("file.txt")
    permissions = oct(file_stats.st_mode)[-3:]
    print(f"文件权限: {permissions}")
    
    # 检查特定权限
    is_readable = bool(file_stats.st_mode & stat.S_IRUSR)
    is_writable = bool(file_stats.st_mode & stat.S_IWUSR)
    is_executable = bool(file_stats.st_mode & stat.S_IXUSR)
    
    print(f"所有者可读: {is_readable}")
    print(f"所有者可写: {is_writable}")
    print(f"所有者可执行: {is_executable}")

# 修改文件权限(Linux/macOS)
if os.name != 'nt':
    os.chmod("file.txt", 0o755)  # rwxr-xr-x
    print(f"修改后的权限: {oct(os.stat('file.txt').st_mode)[-3:]}")

# 修改文件所有者(需要足够权限)
if os.name != 'nt':
    try:
        os.chown("file.txt", 1000, 1000)  # uid=1000, gid=1000
    except PermissionError:
        print("没有权限修改所有者")

3.6 其他功能

文件描述符操作

# 打开文件获取文件描述符
fd = os.open("file.txt", os.O_RDONLY)
print(f"文件描述符: {fd}")

# 读取文件内容
content = os.read(fd, 100)  # 读取100个字节
print(f"读取的内容: {content.decode('utf-8')}")

# 关闭文件描述符
os.close(fd)

# 复制文件描述符
fd1 = os.open("file.txt", os.O_RDONLY)
fd2 = os.dup(fd1)
print(f"原文件描述符: {fd1}, 复制的文件描述符: {fd2}")
os.close(fd1)
os.close(fd2)

随机数生成

# 获取随机字节串
random_bytes = os.urandom(16)  # 生成16个随机字节
print(f"随机字节串: {random_bytes}")
print(f"十六进制表示: {random_bytes.hex()}")

终端大小

# 获取终端大小
try:
    rows, columns = os.popen('stty size', 'r').read().split()
    print(f"终端大小: {rows}行 x {columns}列")
except:
    print("无法获取终端大小")

# 使用os.get_terminal_size(Python 3.3+)
try:
    terminal_size = os.get_terminal_size()
    print(f"终端大小: {terminal_size.lines}行 x {terminal_size.columns}列")
except OSError:
    print("无法获取终端大小")

4. 常用方法总结

4.1 文件和目录操作

函数 描述 示例
os.remove(path) 删除文件 os.remove("file.txt")
os.rename(src, dst) 重命名/移动文件或目录 os.rename("old.txt", "new.txt")
os.replace(src, dst) 重命名文件,会覆盖目标文件 os.replace("old.txt", "new.txt")
os.mkdir(path) 创建目录 os.mkdir("new_dir")
os.makedirs(path, exist_ok=False) 递归创建目录 os.makedirs("a/b/c")
os.rmdir(path) 删除空目录 os.rmdir("empty_dir")
os.removedirs(path) 递归删除目录 os.removedirs("a/b/c")
os.listdir(path) 列出目录内容 os.listdir(".")
os.scandir(path) 高效列出目录内容 with os.scandir(".") as entries:
os.walk(top) 递归遍历目录 for root, dirs, files in os.walk("."):
os.getcwd() 获取当前工作目录 os.getcwd()
os.chdir(path) 改变当前工作目录 os.chdir("/path/to/dir")

4.2 路径操作(os.path)

函数 描述 示例
os.path.join(path1, path2, ...) 拼接路径 os.path.join("a", "b", "c.txt")
os.path.split(path) 拆分路径 os.path.split("a/b/c.txt")
os.path.splitext(path) 拆分扩展名 os.path.splitext("file.txt")
os.path.abspath(path) 获取绝对路径 os.path.abspath("./file.txt")
os.path.normpath(path) 规范化路径 os.path.normpath("a/../b/c.txt")
os.path.exists(path) 检查路径是否存在 os.path.exists("file.txt")
os.path.isfile(path) 检查是否为文件 os.path.isfile("file.txt")
os.path.isdir(path) 检查是否为目录 os.path.isdir("dir")
os.path.islink(path) 检查是否为符号链接 os.path.islink("link.txt")
os.path.getsize(path) 获取文件大小 os.path.getsize("file.txt")
os.path.getmtime(path) 获取修改时间 os.path.getmtime("file.txt")
os.path.getctime(path) 获取创建/元数据修改时间 os.path.getctime("file.txt")

4.3 进程和环境

函数 描述 示例
os.system(command) 执行系统命令 os.system("dir")
os.popen(command) 执行命令并获取输出 os.popen("whoami").read()
os.getpid() 获取当前进程ID os.getpid()
os.getppid() 获取父进程ID os.getppid()
os.environ 获取环境变量 os.environ["PATH"]
os.environ.get(key) 获取环境变量(安全) os.environ.get("HOME")

4.4 系统信息

函数 描述 示例
os.name 获取操作系统名称 os.name
os.uname() 获取Unix系统信息 os.uname()
os.getlogin() 获取当前登录用户 os.getlogin()
os.sep 获取路径分隔符 os.sep
os.pathsep 获取环境变量分隔符 os.pathsep
os.linesep 获取系统换行符 os.linesep

5. 最佳实践

5.1 跨平台兼容性

# 推荐使用os.path.join而不是直接拼接路径
# 错误示例
path = "a" + "/" + "b" + "/" + "c.txt"  # 在Windows上会有问题

# 正确示例
path = os.path.join("a", "b", "c.txt")  # 跨平台兼容

# 使用os.sep而不是硬编码路径分隔符
path = os.sep.join(["a", "b", "c.txt"])

# 检查操作系统
if os.name == 'nt':  # Windows
    # Windows特定代码
    pass
else:  # Linux/macOS
    # Unix特定代码
    pass

5.2 异常处理

# 总是处理文件操作可能的异常
def safe_remove(file_path):
    try:
        os.remove(file_path)
        return True
    except FileNotFoundError:
        print(f"文件不存在: {file_path}")
        return False
    except PermissionError:
        print(f"没有权限删除: {file_path}")
        return False
    except Exception as e:
        print(f"删除文件时出错: {e}")
        return False

# 使用os.path.exists检查路径
if os.path.exists(file_path):
    # 执行操作
    pass
else:
    print(f"路径不存在: {file_path}")

5.3 使用上下文管理器

# 使用with语句管理os.scandir
with os.scandir(".") as entries:
    for entry in entries:
        if entry.is_file():
            print(f"文件: {entry.name}")
        elif entry.is_dir():
            print(f"目录: {entry.name}")
# 自动关闭资源

# 不使用with语句需要手动关闭
entries = os.scandir(".")
try:
    for entry in entries:
        # 处理条目
        pass
finally:
    entries.close()

5.4 避免使用os.system

对于复杂的系统命令,推荐使用subprocess模块而不是os.systemos.popen,因为它提供了更强大和安全的功能:

# 错误示例(不安全,易受命令注入攻击)
user_input = "file.txt; rm -rf /"  # 恶意输入
os.system(f"cat {user_input}")  # 危险!

# 正确示例(安全)
import subprocess
result = subprocess.run(["cat", user_input], capture_output=True, text=True)
print(result.stdout)

5.5 处理大目录

当处理包含大量文件的目录时,使用os.scandir而不是os.listdir,因为它更高效:

# 低效
files = [f for f in os.listdir(".") if os.path.isfile(os.path.join(".", f))]

# 高效
files = [entry.name for entry in os.scandir(".") if entry.is_file()]

6. 常见问题与解决方案

6.1 路径分隔符问题

问题:在不同操作系统上路径分隔符不同(Windows使用\,Linux/macOS使用/

解决方案

  • 使用os.path.join拼接路径
  • 使用os.sep获取当前系统的路径分隔符
  • 使用os.path.normpath规范化路径

6.2 文件权限问题

问题:在Linux/macOS上,无法操作某些文件或目录,出现PermissionError

解决方案

  • 检查文件/目录的权限
  • 确保程序有足够的权限
  • 使用sudo提升权限(仅Linux/macOS)
  • 在Windows上,检查文件是否被其他程序占用

6.3 路径不存在问题

问题:尝试操作不存在的文件或目录,出现FileNotFoundError

解决方案

  • 总是使用os.path.exists检查路径
  • 使用异常处理
  • 创建路径时使用os.makedirs(path, exist_ok=True)避免重复创建

6.4 长路径问题

问题:在Windows上,路径过长可能导致FileNotFoundError

解决方案

  • 使用短路径
  • 在路径前加上\\?\前缀(Windows特有)

6.5 符号链接问题

问题:符号链接的处理可能与普通文件/目录不同

解决方案

  • 使用os.path.islink检查是否为符号链接
  • 使用os.readlink读取符号链接目标
  • 使用os.path.realpath获取符号链接的真实路径

7. 总结

os模块是Python中与操作系统交互的核心模块,提供了丰富的功能,包括:

  1. 文件和目录操作:创建、删除、重命名、遍历等
  2. 路径操作:拼接、拆分、规范化、检查等
  3. 进程管理:执行系统命令、获取进程信息等
  4. 环境变量:获取、设置、删除环境变量
  5. 系统信息:获取操作系统名称、版本、用户等
  6. 权限管理:获取和修改文件权限

使用os模块时,应遵循以下最佳实践:

  • 确保跨平台兼容性
  • 始终处理异常
  • 使用上下文管理器
  • 避免使用不安全的os.system
  • 高效处理大目录

通过掌握os模块的使用,可以编写更强大、更灵活的Python程序,与操作系统进行深度交互,实现各种复杂的任务。


发布网站:荣殿教程(zhangrongdian.com) 作者:张荣殿 发布日期:2026-01-19