os — 多种操作系统接口

源代码: Lib/os.py


  os 模块提供了与操作系统交互的多种功能。可以使用 os 模块来执行文件或目录操作,如读取或修改环境变量、访问命令行参数、处理文件路径、执行系统命令等。

一、相关模块

1.1 os.path 文件路径

  os.path 模块提供了许多用于处理文件和目录路径的功能,包含了跨平台的、对路径名进行操作的功能。

以下是 os.path 模块中一些常用的函数:

  1. os.path.abspath(path)
    返回指定文件或目录的绝对路径。

  2. os.path.basename(path)
    返回指定文件或目录路径的最后一个组成部分,相当于 os.path.split(path)[1]

  3. os.path.commonprefix(lists)
    返回列表中所有路径名共有的最长公共前缀。

  4. os.path.dirname(path)
    返回指定文件或目录路径的目录名称,相当于 os.path.split(path)[0]

  5. os.path.exists(path)
    如果路径存在则返回 True,否则返回 False

  6. os.path.expanduser(path)
    如果路径名以 ~ 开头,则将其替换为当前用户的主目录。

  7. os.path.expandvars(path)
    扩展路径中的环境变量,如 $HOME

  8. os.path.getatime(path)
    返回文件最后访问时间的时间戳。

  9. os.path.getmtime(path)
    返回文件最后修改时间的时间戳。

  10. os.path.getsize(path)
    返回文件的大小(以字节为单位)。

  11. os.path.isabs(path)
    如果路径是绝对路径,则返回 True,否则返回 False

  12. os.path.isfile(path)
    如果路径指向一个存在的文件,则返回 True,否则返回 False

  13. os.path.isdir(path)
    如果路径指向一个存在的目录,则返回 True,否则返回 False

  14. os.path.islink(path)
    如果路径指向一个符号链接,则返回 True,否则返回 False

  15. os.path.ismount(path)
    如果路径指向一个挂载点(如 UNIX 中的挂载文件系统点),则返回 True,否则返回 False

  16. os.path.join(path1, path2, …)
    连接一个或多个路径组件。

  17. os.path.lexists(path)
    如果路径存在(无论它是文件还是目录),则返回 True,否则返回 False

  18. os.path.normcase(path)
    将路径名转换为适当的规范形式。

  19. os.path.normpath(path)
    规范化路径,例如解析 ...

  20. os.path.realpath(path)
    返回指定文件或目录的绝对路径,解析所有符号链接。

  21. os.path.relpath(path, start=None)
    返回从 startpath 的相对路径。

  22. os.path.samefile(path1, path2)
    如果 path1path2 指向同一文件或目录,则返回 True,否则返回 False

  23. os.path.sameopenfile(fp1, fp2)
    如果两个文件描述符 fp1fp2 指向同一文件,则返回 True,否则返回 False

  24. os.path.samestat(stat1, stat2)
    如果两个 stat 对象(通常是通过 os.stat() 获取的)代表同一文件,则返回 True,否则返回 False

  25. os.path.split(path)
    将路径分割为目录和文件名,并返回元组 (dir, file)

  26. os.path.splitext(path)
    分割路径为文件名和扩展名,并返回元组 (filename, extension)

1.2 fileinput 文件读取

  fileinput 允许你轻松地迭代多个输入流(通常是文件),而无需显式地打开和关闭它们。这对于从命令行读取多个文件特别有用,尤其是当你想使用相同的代码逻辑处理多个文件时。

  以下是使用 fileinput 模块的基本示例:

import fileinput

# 处理单个文件
for line in fileinput.input('example.txt'):
    print(line, end='')

# 处理多个文件   
for line in fileinput.input(['file1.txt', 'file2.txt']):
    print(line, end='') 

# 命令行输入
for line in fileinput.input():
    print(line, end='')

fileinput 模块还提供了以下函数:

  • fileinput.filename(): 返回当前正在读取的文件的名称。
  • fileinput.lineno(): 返回当前正在读取的行的行号。
  • fileinput.filelineno(): 返回当前正在读取的行在其文件内的行号。
  • fileinput.isfirstline(): 如果当前行是文件的第一行,则返回 True。
  • fileinput.isstdin(): 如果当前行来自标准输入(即命令行),则返回 True。

1.3 tempfile 临时文件和目录

  tempfile 模块在 Python 中用于创建临时文件和目录。它提供了一种安全、跨平台的方式来处理临时文件,这些文件在程序结束时通常会被自动删除。tempfile 模块中的这些函数和类使得处理临时文件和目录变得简单和安全,尤其是在需要处理敏感数据或避免文件泄露的情况下。

以下是 tempfile 模块中一些常用的函数:

  1. tempfile.TemporaryFile([mode=‘w+b’, buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True])
    创建一个临时文件,并返回一个文件对象。如果 delete 参数为 True(默认值),则文件会在关闭后自动删除。

  2. tempfile.NamedTemporaryFile([mode=‘w+b’, buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True])
    类似于 TemporaryFile,但返回一个文件对象,并且该文件有一个确定的文件名,可以通过文件对象的 name 属性来访问。

  3. tempfile.TemporaryDirectory([suffix=None, prefix=None, dir=None])
    创建一个临时目录,并返回一个 TemporaryDirectory 对象。当对象被销毁时,目录及其内容会被自动删除。

  4. tempfile.mkstemp([suffix, prefix, dir, text])
    生成一个唯一的临时文件名,但不创建文件。返回文件描述符和文件路径。

  5. tempfile.mkdtemp([suffix, prefix, dir])
    生成一个唯一的临时目录名,并创建该目录。返回目录路径。

  6. tempfile.gettempdir()
    返回用于创建临时文件和目录的默认目录。

  7. tempfile.gettempprefix()
    返回用于生成临时文件名和目录名的默认前缀。

  8. tempfile.tempfile.tempdir
    这是一个变量,可以设置或获取用于创建临时文件和目录的默认目录。

以下是 tempfile 模块的函数示例:

import tempfile

# 创建一个临时文件
with tempfile.TemporaryFile() as tmp:
    tmp.write(b'Hello, world!')
    tmp.seek(0)
    print(tmp.read())

# 创建一个有名字的临时文件
with tempfile.NamedTemporaryFile(delete=False) as tmp:
    tmp.write(b'Hello, named temp file!')
    tmp.seek(0)
    print(tmp.read())
    # 文件不会被自动删除,因为它是在 delete=False 下创建的
    # 你可以通过 tmp.name 访问其文件名

# 创建一个临时目录
with tempfile.TemporaryDirectory() as tmpdir:
    print(f"Created temporary directory: {tmpdir}")
    # 在这个 with 块内,tmpdir 存在
    # 当 with 块结束时,tmpdir 和其内容会被自动删除

# 生成一个唯一的临时文件名,但不创建文件
fd, path = tempfile.mkstemp()
print(f"Unique temporary file name: {path}")
# 需要自己关闭文件描述符
os.close(fd)

# 生成一个唯一的临时目录名,并创建该目录
path = tempfile.mkdtemp()
print(f"Unique temporary directory: {path}")
# 需要自己手动删除目录
os.rmdir(path)

1.4 shutil 高级文件和目录

  shutil 提供了高级的文件、文件夹和文件流操作,使得文件和文件夹的操作更加便捷。当需要执行比简单的文件读写更复杂的操作时,通常会使用 shutilshutil 是 “shell utilities” 的缩写,意味着它提供了一些类似于 Unix shell 命令的功能。

以下是一些 shutil 模块中常用的函数:

  1. shutil.copy(src, dst)
    复制文件从 srcdst

  2. shutil.copy2(src, dst)
    复制文件,并尝试保留文件的元数据(如修改时间、访问权限等)。

  3. shutil.copytree(src, dst, symlinks=False, ignore=None)
    递归地复制整个文件夹及其内容。

  4. shutil.rmtree(path, ignore_errors=False, οnerrοr=None)
    递归地删除整个文件夹及其内容。

  5. shutil.move(src, dst)
    将文件或文件夹从 src 移动到 dst

  6. shutil.make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None)
    创建一个归档文件(如 ZIP、TAR 等)。

  7. shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None)
    查找可执行文件的路径。

  8. shutil.register_archive_format(name, function, extra_args=None, description=None)
    注册一个新的归档格式。

  9. shutil.unregister_archive_format(name)
    取消注册一个归档格式。

以下是 shutil 模块的函数示例:

import shutil

# 复制文件
shutil.copy('source.txt', 'destination.txt')

# 复制文件夹
shutil.copytree('source_folder', 'destination_folder')

# 删除文件夹
shutil.rmtree('folder_to_remove')

# 移动文件
shutil.move('old_name.txt', 'new_name.txt')

# 创建 ZIP 归档
shutil.make_archive('my_archive', 'zip', 'path_to_folder_to_archive')

# 查找特定命令的路径
path_to_python = shutil.which('python')
print(f"Path to python: {path_to_python}")

1.5 platform 操作系统底层模块

  platform 提供了许多与底层平台相关的信息,如操作系统的名称、版本、架构等。使用 platform 模块可以编写更可移植的代码,因为可以根据运行代码的操作系统来做出不同的行为或决策。

  这个模块允许在不知道代码将在哪种操作系统上运行时,仍然能够收集有关底层系统的有用信息。在编写需要适应不同环境的软件时,这是非常有帮助的。

以下是 platform 模块中常用的属性:

  1. platform.system()
    返回操作系统名称,例如 ‘Windows’, ‘Linux’, ‘Darwin’(对于 MacOS)。

  2. platform.node()
    返回机器的主机名。

  3. platform.release()
    返回操作系统的发行版本号。

  4. platform.version()
    返回操作系统的版本信息。

  5. platform.machine()
    返回机器的硬件名称,例如 ‘x86’, ‘AMD64’, ‘ARM’。

  6. platform.processor()
    返回机器的处理器名称,例如 ‘Intel64 Family 6 Model 158 Stepping 9, GenuineIntel’。

  7. platform.python_version()
    返回 Python 解释器的版本。

  8. platform.python_compiler()
    返回用于编译 Python 解释器的编译器。

  9. platform.python_branch()
    返回 Python 解释器的分支名称。

  10. platform.python_revision()
    返回 Python 解释器的修订版本号。

  11. platform.python_build()
    返回 Python 解释器的构建时间戳和构建标识符。

  12. platform.python_implementation()
    返回 Python 解释器的实现名称,例如 ‘CPython’, ‘Jython’, ‘IronPython’。

以下是 platform 模块中常用的函数:

  1. platform.uname()
    返回一个包含五个属性的元组,与 POSIX uname 命令返回的类似,包括系统名称、节点名称、发布版本、版本和机器名称。

  2. platform.architecture()
    返回一个元组,包含位大小和链接的库名称。

  3. platform.libc_ver()
    返回 C 库版本信息,通常是一个包含两个元素的元组。

以下是 platform 模块的函数示例:

import platform

# 输出操作系统信息
print("Operating System:", platform.system())
print("Release Version:", platform.release())
print("Machine Hardware:", platform.machine())
print("Processor:", platform.processor())

# 输出Python解释器信息
print("Python Version:", platform.python_version())
print("Python Compiler:", platform.python_compiler())
print("Python Branch:", platform.python_branch())
print("Python Revision:", platform.python_revision())

# 获取更多信息
print("OS name and version:", platform.platform())
print("OS uname info:", platform.uname())
print("Architecture info:", platform.architecture())
print("C library version:", platform.libc_ver())

二、关于函数适用性的说明

2.1 与操作系统相同的接口

  Python中所有依赖于操作系统的内置模块的设计都是一样,只要不同的操作系统某一相同的功能可用,它就使用相同的接口。

  例如,函数 os.stat(path) 以相同的格式返回关于 path 的状态信息(该格式源于 POSIX 接口)。

  特定于某一操作系统的扩展通过操作 os 模块也是可用的,但是使用它们是对可移植性的一种威胁。

2.2 支持字节串和字符串

  所有接受路径或文件名的函数都同时支持字节串和字符串对象,并在返回路径或文件名时使用相应类型的对象作为结果。

2.3 exception OSError

  如果使用无效或无法访问的文件名与路径,或者其他类型正确但操作系统不接受的参数,os模块的所有函数都抛出 OSError (或者它的子类)。OSError的别名是os.error

三、文件名,命令行参数,以及环境变量

  在 Python 中,使用字符串类型表示文件名、命令行参数和环境变量。 在某些系统上,在将这些字符串传递给操作系统之前,必须将这些字符串解码为字节。

  Python 使用 filesystem encoding and error handler 来执行此转换,可以通过 sys.getfilesystemencoding() 获取在文件系统中编码文件名的字符串。这通常与操作系统的默认文件系统编码有关。

  例如,在 Unix 和 Linux 系统中,默认的文件系统编码通常是 ‘UTF-8’。而在 Windows 中,这取决于系统配置和版本,但通常是 ‘cp1252’。

  这里是一个简单的例子来演示如何使用这个函数:

import sys

filesystem_encoding = sys.getfilesystemencoding()
print("Filesystem encoding:", filesystem_encoding)

注意:文件系统编码可能不同于 Python 解释器用来解释源代码的编码,后者可以通过在源代码文件的开头添加特殊的注释来指定(例如 # coding: utf-8

  filesystem encoding and error handler 是在 Python 启动时通过 PyConfig_Read() 函数来配置的:请参阅 PyConfigfilesystem_encodingfilesystem_errors 等成员。

  文件系统编码器 必须保证能成功解码所有 128 以内的字节。如果不能保证,API 函数可能触发 UnicodeError

四 文件系统编码格式与错误处理句柄

  filesystem encoding and error handler 是Python 用来从操作系统解码字节串和向操作系统编码 Unicode 的编码格式与错误处理句柄。

  文件系统编码格式必须保证能成功解码长度在 128 以下的所有字节串。 如果文件系统编码格式无法提供此保证,则 API 函数可能会引发 UnicodeError

  sys.getfilesystemencoding()sys.getfilesystemencodeerrors() 函数可被用来获取文件系统编码格式与错误处理句柄。

  filesystem encoding and error handler是在 Python 启动时通过 PyConfig_Read()函数来配置的:请查阅 PyConfigfilesystem_encodingfilesystem_errors

五、locale encoding – 语言区域编码格式

  在 Unix 上,它是 LC_CTYPE 语言区域的编码格式。 它可以通过 locale.setlocale(locale.LC_CTYPE, new_locale) 来设置。

  在 Windows 上,它是 ANSI 代码页 (如: "cp1252")。

  在 Android 和 VxWorks 上,Python 使用 "utf-8" 作为语言区域编码格式。

  locale.getencoding() 可被用来获取语言区域编码格式。

六、Python UTF-8 模式

  Python UTF-8 模式是一个特殊的模式,此模式会忽略 locale encoding 并强制使用 UTF-8 编码。如果在 Python 启动时 LC_CTYPE 区域设为 CPOSIX ,则启用 Python UTF-8 模式 (参见 PyConfig_Read() 函数)。它可以通过命令行选项 -X utf8 和环境变量 PYTHONUTF8,来启用或禁用。

  如果没有设置 PYTHONUTF8 环境变量,那么解释器默认使用当前的地区设置,除非 当前地区识别为基于 ASCII 的传统地区(如 PYTHONCOERCECLOCALE 所述),并且 locale coercion 被禁用或失败。在这种传统地区,除非显式指明不要如此,解释器将默认启用 UTF-8 模式。Python UTF-8 模式只能在 Python 启动时启用。其值可以从 sys.flags.utf8_mode 读取。

  当处在Python UTF-8 模式下时,会出现以下特征:

  1. 用 UTF-8 作为 文件系统编码。
  2. sys.getfilesystemencoding() 返回 'utf-8'
  3. locale.getpreferredencoding() 返回 'utf-8' (do_setlocale 参数不起作用)。
  4. sys.stdin, sys.stdoutsys.stderr 都将 UTF-8 用作它们的文本编码,并且为 sys.stdinsys.stdout 启用 surrogateescape 错误处理句柄 (sys.stderr 会继续使用 backslashreplace 如同在默认的局部感知模式下一样)
  5. 在 Unix 上,os.device_encoding() 返回 'utf-8' 而不是设备的编码格式。

注意 UTF-8 模式下的标准流设置可以被 PYTHONIOENCODING 所覆盖(在默认的区域感知模式下也同样如此)。

  当低层级 API切换到UTF-8编码后,其他高层级 API 也相应改变:

  • 命令行参数,环境变量和文件名会使用 UTF-8 编码来解码为文本。
  • os.fsdecode()os.fsencode() 会使用 UTF-8 编码。
  • open(), io.open()codecs.open() 默认会使用 UTF-8 编码。 但是,它们默认仍将使用严格错误处理句柄,因此试图在文本模式下打开二进制文件将可能引发异常,而不是生成无意义的数据。

(未完待续……)

may the odds be ever in your favor ~

03-04 06:13