MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python文件路径与操作

2021-08-153.3k 阅读

1. Python中的文件路径表示

在Python中,操作文件和目录时,准确表示文件路径至关重要。Python支持多种操作系统,不同操作系统的文件路径表示有所差异。

1.1 Windows系统下的文件路径

在Windows系统中,文件路径使用反斜杠 \ 作为目录分隔符。例如,要表示 C 盘下 Users 文件夹中 John 用户的文档文件夹路径,可写为:C:\Users\John\Documents。然而,在Python字符串中,反斜杠是转义字符,所以直接写 'C:\Users\John\Documents' 会引发错误,因为 \U\J 等组合可能被误解为转义序列。为解决这个问题,有几种方法。

一种方法是使用双反斜杠,如 'C:\\Users\\John\\Documents'。另一种常用方法是使用原始字符串,在字符串前加上 r 前缀,这样字符串中的反斜杠就不会被当作转义字符处理,如 r'C:\Users\John\Documents'

# 使用双反斜杠表示路径
path1 = 'C:\\Users\\John\\Documents'
print(path1)

# 使用原始字符串表示路径
path2 = r'C:\Users\John\Documents'
print(path2)

1.2 Unix和类Unix系统(如Linux、macOS)下的文件路径

在Unix和类Unix系统中,文件路径使用正斜杠 / 作为目录分隔符。例如,用户 John 的主目录下的文档文件夹路径可表示为:/home/John/Documents。在Python中处理这类路径时,无需像Windows那样特别处理转义问题,直接使用正斜杠即可。

# Unix和类Unix系统下的路径表示
path_unix = '/home/John/Documents'
print(path_unix)

1.3 跨平台路径表示

为了编写可在不同操作系统上运行的代码,Python提供了 os.path 模块,其中的 os.path.join() 函数可根据当前操作系统自动选择正确的目录分隔符来拼接路径。

import os

# 跨平台路径拼接
dirname = 'Users'
subdirname = 'John'
filename = 'document.txt'
path = os.path.join('C:', dirname, subdirname, filename)
print(path)

在Windows系统上,上述代码会输出 C:\Users\John\document.txt,而在Unix或类Unix系统上,若将 'C:' 替换为适当的根目录,会输出类似 /Users/John/document.txt 的路径。

2. 操作文件路径的常用模块

2.1 os模块

os 模块是Python标准库中用于与操作系统交互的重要模块,包含了大量操作文件和目录路径的函数。

2.1.1 获取当前工作目录 使用 os.getcwd() 函数可以获取当前Python脚本所在的工作目录。

import os

current_dir = os.getcwd()
print(f"当前工作目录: {current_dir}")

2.1.2 改变当前工作目录 os.chdir() 函数用于改变当前工作目录。例如,要将当前工作目录切换到 C:\Users\John\Documents(在Windows系统下),可以这样做:

import os

new_dir = r'C:\Users\John\Documents'
os.chdir(new_dir)
current_dir = os.getcwd()
print(f"切换后的当前工作目录: {current_dir}")

2.1.3 拆分路径 os.path.split() 函数可以将路径拆分为目录部分和文件名部分。

import os

path = r'C:\Users\John\Documents\document.txt'
directory, filename = os.path.split(path)
print(f"目录: {directory}")
print(f"文件名: {filename}")

2.1.4 获取路径中的文件名 os.path.basename() 函数专门用于获取路径中的文件名部分。

import os

path = r'C:\Users\John\Documents\document.txt'
filename = os.path.basename(path)
print(f"文件名: {filename}")

2.1.5 获取路径中的目录部分 os.path.dirname() 函数则用于获取路径中的目录部分。

import os

path = r'C:\Users\John\Documents\document.txt'
directory = os.path.dirname(path)
print(f"目录: {directory}")

2.1.6 检查路径是否存在 os.path.exists() 函数可用于检查指定的路径是否存在。

import os

path = r'C:\Users\John\Documents'
if os.path.exists(path):
    print(f"{path} 存在")
else:
    print(f"{path} 不存在")

2.1.7 判断是否为目录 os.path.isdir() 函数用于判断给定路径是否为一个目录。

import os

path = r'C:\Users\John\Documents'
if os.path.isdir(path):
    print(f"{path} 是一个目录")
else:
    print(f"{path} 不是一个目录")

2.1.8 判断是否为文件 os.path.isfile() 函数用于判断给定路径是否为一个文件。

import os

path = r'C:\Users\John\Documents\document.txt'
if os.path.isfile(path):
    print(f"{path} 是一个文件")
else:
    print(f"{path} 不是一个文件")

2.2 pathlib模块

pathlib 模块是Python 3.4 引入的标准库,它提供了一种面向对象的方式来处理文件系统路径。相比 os.pathpathlib 更加直观和易用,尤其在处理复杂路径操作时。

2.2.1 创建路径对象 pathlib.Path() 类可用于创建路径对象。根据传入的参数不同,它会根据当前操作系统自动创建相应格式的路径对象。

from pathlib import Path

# 创建一个表示当前目录的路径对象
current_dir = Path('.')
print(current_dir)

# 创建一个绝对路径对象
abs_path = Path(r'C:\Users\John\Documents')
print(abs_path)

2.2.2 获取路径属性 路径对象有许多属性可以获取路径的相关信息。例如,name 属性获取文件名,parent 属性获取父目录路径对象。

from pathlib import Path

path = Path(r'C:\Users\John\Documents\document.txt')
print(f"文件名: {path.name}")
print(f"父目录: {path.parent}")

2.2.3 路径操作 路径对象支持一些方便的操作方法。例如,joinpath() 方法用于拼接路径,类似 os.path.join()

from pathlib import Path

parent_dir = Path(r'C:\Users\John')
sub_dir = 'Documents'
filename = 'document.txt'
new_path = parent_dir.joinpath(sub_dir, filename)
print(new_path)

2.2.4 检查路径状态 路径对象也有方法用于检查路径是否存在、是否为目录或文件等。

from pathlib import Path

path = Path(r'C:\Users\John\Documents')
if path.exists():
    if path.is_dir():
        print(f"{path} 是一个存在的目录")
    elif path.is_file():
        print(f"{path} 是一个存在的文件")
else:
    print(f"{path} 不存在")

3. 文件操作基础

3.1 打开文件

在Python中,使用 open() 函数来打开文件。open() 函数接受文件名(路径)和打开模式作为参数。常见的打开模式有:

  • 'r':只读模式,用于读取文件内容,文件必须存在,否则会报错。
  • 'w':写入模式,用于写入文件内容。如果文件不存在,会创建新文件;如果文件已存在,会清空原有内容。
  • 'a':追加模式,用于在文件末尾追加内容。如果文件不存在,会创建新文件。
# 以只读模式打开文件
try:
    file = open('example.txt', 'r')
    content = file.read()
    print(content)
    file.close()
except FileNotFoundError:
    print("文件未找到")
# 以写入模式打开文件
file = open('new_file.txt', 'w')
file.write("这是新写入的内容")
file.close()
# 以追加模式打开文件
file = open('example.txt', 'a')
file.write("\n这是追加的内容")
file.close()

3.2 读取文件

3.2.1 读取整个文件内容 当以只读模式打开文件后,可以使用 read() 方法读取整个文件内容。

try:
    file = open('example.txt', 'r')
    content = file.read()
    print(content)
    file.close()
except FileNotFoundError:
    print("文件未找到")

3.2.2 逐行读取文件内容 对于较大的文件,逐行读取可以节省内存。可以使用 readline() 方法逐行读取,或者使用 for 循环直接迭代文件对象。

try:
    file = open('example.txt', 'r')
    line = file.readline()
    while line:
        print(line.strip())
        line = file.readline()
    file.close()
except FileNotFoundError:
    print("文件未找到")
try:
    with open('example.txt', 'r') as file:
        for line in file:
            print(line.strip())
except FileNotFoundError:
    print("文件未找到")

3.3 写入文件

3.3.1 写入字符串内容 使用 write() 方法可以将字符串写入文件。

file = open('new_file.txt', 'w')
file.write("这是要写入的新内容")
file.close()

3.3.2 写入多行内容 如果要写入多行内容,可以使用 writelines() 方法,它接受一个字符串序列(如列表)。

lines = ["第一行内容\n", "第二行内容\n"]
file = open('new_lines.txt', 'w')
file.writelines(lines)
file.close()

3.4 关闭文件

在对文件操作完成后,及时关闭文件是很重要的。可以使用 close() 方法关闭文件。

file = open('example.txt', 'r')
content = file.read()
print(content)
file.close()

另外,使用 with 语句可以更安全地处理文件,它会在代码块结束时自动关闭文件,无需显式调用 close()

with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

4. 高级文件操作

4.1 文件指针操作

文件指针用于指示当前在文件中的位置。在读取或写入文件时,文件指针会自动移动。可以使用 seek() 方法手动移动文件指针,使用 tell() 方法获取当前文件指针的位置。

4.1.1 seek()方法 seek(offset, whence) 方法有两个参数,offset 表示偏移量,whence 表示参考位置。whence 的值可以是:

  • 0:从文件开头开始计算偏移量(默认值)。
  • 1:从当前文件指针位置开始计算偏移量。
  • 2:从文件末尾开始计算偏移量。
file = open('example.txt', 'r')
# 将文件指针移动到文件开头后第5个字节的位置
file.seek(5, 0)
content = file.read()
print(content)
file.close()
file = open('example.txt', 'r')
# 从当前位置向后移动3个字节
file.seek(3, 1)
content = file.read()
print(content)
file.close()
file = open('example.txt', 'r')
# 从文件末尾向前移动10个字节
file.seek(-10, 2)
content = file.read()
print(content)
file.close()

4.1.2 tell()方法 tell() 方法返回当前文件指针的位置。

file = open('example.txt', 'r')
position = file.tell()
print(f"初始文件指针位置: {position}")
content = file.read(5)
position = file.tell()
print(f"读取5个字节后的文件指针位置: {position}")
file.close()

4.2 文件权限操作

在Unix和类Unix系统中,可以使用 os.chmod() 函数来改变文件的权限。文件权限用八进制数表示,例如 0o755 表示文件所有者有读、写、执行权限,组用户和其他用户有读和执行权限。

import os

file_path = 'example.txt'
# 将文件权限设置为0o755
os.chmod(file_path, 0o755)

4.3 硬链接和软链接

4.3.1 硬链接 在Unix和类Unix系统中,可以使用 os.link() 函数创建硬链接。硬链接是文件的另一个名称,与原文件共享相同的inode(索引节点),因此具有相同的内容和属性。

import os

original_file = 'original.txt'
hard_link = 'hard_link.txt'
os.link(original_file, hard_link)

4.3.2 软链接(符号链接) 使用 os.symlink() 函数可以创建软链接。软链接是一个指向原文件的特殊文件,它有自己的inode,内容是原文件的路径。

import os

original_file = 'original.txt'
soft_link ='soft_link.txt'
os.symlink(original_file, soft_link)

5. 目录操作

5.1 创建目录

5.1.1 使用os模块创建目录 使用 os.mkdir() 函数可以创建一个新目录。该函数只能创建单层目录,如果父目录不存在,会报错。

import os

new_dir = 'new_directory'
os.mkdir(new_dir)

要创建多层目录,可以使用 os.makedirs() 函数,它会自动创建所有不存在的父目录。

import os

nested_dir = 'parent/child/grandchild'
os.makedirs(nested_dir)

5.1.2 使用pathlib模块创建目录 使用 pathlib.Path 对象的 mkdir() 方法也可以创建目录。

from pathlib import Path

new_dir = Path('new_directory')
new_dir.mkdir()

要创建多层目录,可以传递 parents=True 参数。

from pathlib import Path

nested_dir = Path('parent/child/grandchild')
nested_dir.mkdir(parents=True)

5.2 删除目录

5.2.1 使用os模块删除目录 使用 os.rmdir() 函数可以删除一个空目录。如果目录不为空,会报错。

import os

empty_dir = 'empty_directory'
os.rmdir(empty_dir)

要删除非空目录及其所有内容,可以使用 shutil.rmtree() 函数。

import os
import shutil

non_empty_dir = 'non_empty_directory'
shutil.rmtree(non_empty_dir)

5.2.2 使用pathlib模块删除目录 pathlib.Path 对象的 rmdir() 方法同样只能删除空目录。

from pathlib import Path

empty_dir = Path('empty_directory')
empty_dir.rmdir()

5.3 遍历目录

5.3.1 使用os模块遍历目录 os.walk() 函数可以递归地遍历一个目录及其所有子目录。它返回一个三元组 (dirpath, dirnames, filenames),其中 dirpath 是当前目录路径,dirnames 是当前目录下的子目录名列表,filenames 是当前目录下的文件名列表。

import os

for root, dirs, files in os.walk('.'):
    print(f"当前目录: {root}")
    print(f"子目录: {dirs}")
    print(f"文件: {files}")

5.3.2 使用pathlib模块遍历目录 pathlib.Path 对象的 iterdir() 方法可以迭代当前目录下的所有文件和目录。要递归遍历,可以使用 rglob() 方法。

from pathlib import Path

current_dir = Path('.')
for item in current_dir.iterdir():
    if item.is_dir():
        print(f"目录: {item}")
    elif item.is_file():
        print(f"文件: {item}")
from pathlib import Path

current_dir = Path('.')
for item in current_dir.rglob('*'):
    if item.is_dir():
        print(f"目录: {item}")
    elif item.is_file():
        print(f"文件: {item}")

6. 文件和目录的复制、移动与重命名

6.1 复制文件和目录

6.1.1 使用shutil模块复制文件 shutil.copy() 函数用于复制文件,它接受源文件路径和目标路径作为参数。如果目标路径是一个目录,文件会被复制到该目录下,文件名保持不变。

import shutil

source_file = 'original.txt'
destination_dir = 'new_folder'
shutil.copy(source_file, destination_dir)

shutil.copy2() 函数类似 shutil.copy(),但它会尝试保留文件的元数据(如修改时间等)。

import shutil

source_file = 'original.txt'
destination_dir = 'new_folder'
shutil.copy2(source_file, destination_dir)

6.1.2 使用shutil模块复制目录 shutil.copytree() 函数用于递归复制整个目录及其所有内容。

import shutil

source_dir = 'original_folder'
destination_dir = 'new_folder'
shutil.copytree(source_dir, destination_dir)

6.2 移动文件和目录

6.2.1 使用os模块移动文件和目录 os.rename() 函数可以用于移动文件或目录,也可以用于重命名。如果目标路径与源路径在不同目录,实际上就是移动操作。

import os

source_file = 'old_name.txt'
destination_file = 'new_folder/new_name.txt'
os.rename(source_file, destination_file)

6.2.2 使用shutil模块移动文件和目录 shutil.move() 函数也可以用于移动文件和目录,它在处理跨文件系统的移动时更加健壮。

import shutil

source_file = 'old_name.txt'
destination_file = 'new_folder/new_name.txt'
shutil.move(source_file, destination_file)

6.3 重命名文件和目录

如上述 os.rename() 函数的示例,将文件移动到同一目录下并更改文件名,就是重命名操作。同样,shutil.move() 函数也可以用于重命名。

import os

old_dir_name = 'old_folder'
new_dir_name = 'new_folder'
os.rename(old_dir_name, new_dir_name)

7. 处理特殊文件类型

7.1 二进制文件操作

在处理二进制文件(如图片、音频、视频等)时,需要以二进制模式打开文件。在 open() 函数中,使用 'rb' 表示只读二进制模式,'wb' 表示写入二进制模式。

# 读取二进制文件
try:
    with open('image.jpg', 'rb') as file:
        binary_data = file.read()
        print(f"读取的二进制数据长度: {len(binary_data)}")
except FileNotFoundError:
    print("文件未找到")
# 写入二进制文件
binary_data = b'\x48\x65\x6c\x6c\x6f'  # 示例二进制数据
with open('new_binary_file.bin', 'wb') as file:
    file.write(binary_data)

7.2 压缩文件操作

7.2.1 使用zipfile模块处理ZIP文件 zipfile 模块可用于创建、读取和提取ZIP压缩文件。

import zipfile

# 创建ZIP文件
with zipfile.ZipFile('archive.zip', 'w') as zipf:
    zipf.write('file1.txt')
    zipf.write('file2.txt')
# 读取ZIP文件内容
with zipfile.ZipFile('archive.zip', 'r') as zipf:
    print(f"ZIP文件中的文件: {zipf.namelist()}")
# 提取ZIP文件内容
with zipfile.ZipFile('archive.zip', 'r') as zipf:
    zipf.extractall('extracted_folder')

7.2.2 使用tarfile模块处理TAR文件 在Unix和类Unix系统中,tarfile 模块用于处理TAR文件(通常与 .gz 等压缩格式结合使用)。

import tarfile

# 创建TAR文件
with tarfile.open('archive.tar', 'w') as tarf:
    tarf.add('file1.txt')
    tarf.add('file2.txt')
# 读取TAR文件内容
with tarfile.open('archive.tar', 'r') as tarf:
    print(f"TAR文件中的文件: {tarf.getnames()}")
# 提取TAR文件内容
with tarfile.open('archive.tar', 'r') as tarf:
    tarf.extractall('extracted_folder')

通过以上对Python文件路径与操作的详细介绍,希望读者能全面掌握在Python中高效处理文件和目录的各种方法,无论是简单的文件读写,还是复杂的目录遍历、文件权限操作等,都能得心应手。在实际开发中,根据具体需求选择合适的模块和方法,以实现稳健、高效的文件系统操作。