乐趣区

关于操作系统:Python-os-模块详解

你好,我是悦创。

此篇文章,是为了欠缺 Python 办公自动化的课程,有趣味的报名一对一办公自动化的小伙伴,能够加 V:Jiabcdefh。

如果咱们要操作文件、目录,能够在命令行上面输出操作系统提供的各种命令来实现。比方 dir、cp 等命令。

如果要在 Python 程序中执行这些目录和文件的操作怎么办?

<font color=”red”> 其实操作系统提供的命令只是简略地调用了操作系统提供的接口函数,Python 内置的 os 模块也能够间接调用操作系统提供的接口函数。</font>

1. 简介

os 就是“operating system”的缩写,顾名思义,os 模块提供的就是各种 Python 程序与操作系统进行交互的接口。通过应用 os 模块,一方面能够不便地与操作系统进行交互,另一方面页能够极大加强代码的可移植性。如果该模块中相干性能出错,会抛出 OSError 异样或其子类异样。

留神: 本模块提供了一种应用与操作系统相干的性能的便捷式路径。如果是读写文件的话,倡议应用内置函数 open();如果是门路相干的操作,倡议应用 os 的子模块 os.path;如果要逐行读取多个文件,倡议应用 fileinput 模块;要创立临时文件或门路,倡议应用 tempfile 模块;要进行更高级的文件和门路操作则该当应用 shutil 模块。

当然,应用 os 模块能够写出操作系统无关的代码,并不意味着 os 无奈调用一些特定零碎的扩大性能,但要切记一点:一旦这样做就会极大 侵害代码的可移植性

此外,导入 os 模块时还要小心一点,千万 不要 为了图调用省事儿而将os 模块解包导入,即不要应用:

 from os import *

来导入os 模块;否则 os.open() 将会笼罩内置函数 open(),从而造成意料之外的谬误。

2. 罕用性能

留神os 模块中大多数承受门路作为参数的函数也能够承受“文件描述符”作为参数。

文件描述符: file descriptor,在 Python 文档中简记为 fd,是一个与某个关上的文件对象绑定的整数,能够了解为该文件在零碎中的编号。

2.1 os.name

该属性宽泛地指明了以后 Python 运行所在的环境,实际上是导入的操作系统相干模块的名称。这个名称也决定了模块中 哪些性能是可用 的,哪些是没有相应实现的。

目前无效名称为以下三个:posixntjava

其中:

  • posix 是 Portable Operating System Interface of UNIX(可移植操作系统接口)的缩写。Linux 和 Mac OS 均会返回该值;
  • nt 全称应为“Microsoft Windows NT”,大体能够等同于 Windows 操作系统,因而 Windows 环境下会返回该值;
  • java 则是 Java 虚拟机环境下的返回值。

总之:如果是 posix,阐明零碎是 Linux、Unix 或 Mac OS X,如果是 nt,就是 Windows 零碎。

因而在我的电脑(win10)上执行下述代码,返回值是 nt

In [1]: import os

In [2]: os.name
Out[2]: 'nt'

而在 WSL(Windows Subsystem Linux,Windows 下的 Linux 子系统)上的后果则是:

In [2]: import os

In [3]: os.name
Out[3]: 'posix'

查看 sys 模块中的 sys.platform 属性能够失去对于运行平台更具体的信息,在此不再赘述

Windows10:

In [4]: sys.platform
Out[4]: 'win32'

Linux:

In [5]: sys.platform
Out[5]: 'linux'

PS: 要获取具体的零碎信息,能够调用 uname() 函数:

In [6]: os.uname()
Out[6]: posix.uname_result(sysname='Linux', nodename='aiyc', release='5.11.0-34-generic', version='#36~20.04.1-Ubuntu SMP Fri Aug 27 08:06:32 UTC 2021', machine='x86_64')

留神 uname() 函数在 Windows 上不提供,也就是说,os 模块的某些函数是跟操作系统相干的。

2.2 环境变量 os.environ

os.environ 属性能够返回环境相干的信息,次要是各类环境变量。返回值是一个映射(相似字典类型),具体的值为第一次导入 os 模块时的快照;其中的各个键值对,键是环境变量名,值则是环境变量对应的值。在第一次导入 os 模块之后,除非间接批改 os.environ 的值,否则该属性的值不再发生变化。

在操作系统中定义的环境变量,全副保留在 os.environ 这个变量中,能够间接查看:

In [8]: os.environ
Out[8]:
environ{'ALLUSERSPROFILE': 'C:\\ProgramData',
        'ANSICON': '75x32766 (75x24)',
        'ANSICON_DEF': '7',
        'APPDATA': 'C:\\Users\\clela\\AppData\\Roaming',
        'CHOCOLATEYINSTALL': 'C:\\ProgramData\\chocolatey',
        'CHOCOLATEYLASTPATHUPDATE': '132726379469707878',
        'CLASSPATH': '.;C:\\java\\lib\\dt.jar;C:\\java\\lib\\tools.jar;',
        'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files',...}

要获取某个环境变量的值,能够调用 os.environ.get('key') 比方其中键为“HOMEPATH”(Windows 下,Linux 下为“HOME”)的项,对应的值就是用户主目录的门路。Windows 下,其值为:

In [9]: os.environ["HOMEPATH"]
Out[9]: '\\Users\\clela'

Linux 下,其值为:

In [17]: os.environ["HOME"]
Out[17]: '/home/aiyc'

2.3 os.walk()

这个函数须要传入一个门路作为 top 参数,函数的作用是在以 top 为根节点的目录树中游走,对树中的每个目录生成一个由 (dirpath, dirnames, filenames) 三项组成的三元组。

其中:

  • dirpath 是一个批示这个目录门路的字符串,
  • dirnames 是一个 dirpath 下子目录名(除去 “.”“..”)组成的 列表filenames 则是由 dirpath 下所有非目录的文件名组成的列表。
  • 要留神的是,这些名称并不蕴含所在门路自身,要获取 dirpath 下某个文件或门路从 top 目录开始的残缺门路,须要应用 os.path.join(dirpath, name)

留神最终返回的后果是一个迭代器,咱们能够应用 for 语句一一获得迭代器的每一项:

for item in os.walk("."):
    print(item)
('.', ['do'], ['go_go_go.txt'])
('.\\do', ['IAmDirectory', 'python'], [])
('.\\do\\IAmDirectory', [], [])
('.\\do\\python', [], ['hello_justdopython.txt'])

实例二:

import os

for pt in os.walk("."):
    print(pt)
('.', ['Tester2Folder', 'TesterFolder'], ['OS-AlexSmith_2021 - 正本 (2).txt', 'OS-AlexSmith_2021 - 正本 (3).txt', 'OS-AlexSmith_2021 - 正本.txt', 'OS-AlexSmith_2021.txt', 'OS-I_Have_a_Dream - 正本 (2).txt', 'OS-I_Have_a_Dream - 正本.txt', 'OS-I_Have_a_Dream.txt', 'OS-WordCount_Basic - 正本 (2).py', 'OS-WordCount_Basic - 正本.py', 'OS-WordCount_Basic.py', 'OS_Page.py'])
('.\\Tester2Folder', ['Tester2Folder_test'], ['Tester2Folder-AlexSmith_2021 - 正本 (2).txt', 'Tester2Folder-AlexSmith_2021 - 正本 (3).txt', 'Tester2Folder-AlexSmith_2021 - 正本 (4).txt', 'Tester2Folder-AlexSmith_2021 - 正本.txt', 'Tester2Folder-AlexSmith_2021.txt', 'Tetser2-WordCount_Basic.py'])
('.\\Tester2Folder\\Tester2Folder_test', [], [])
('.\\TesterFolder', [], ['TesterFolder-I_Have_a_Dream - 正本.txt', 'TesterFolder-I_Have_a_Dream.txt', 'TesterFolder-Tester-I_Have_a_Dream - 正本 (2).txt', 'TesterFolder-Tester-I_Have_a_Dream - 正本 (3).txt', 'TesterFolder-WordCount_Basic.py'])

2.4 os.listdir()

listdirlist directories,列出(以后)目录下的全副门路(及文件)。该函数存在一个参数,用以指定要列出子目录的门路,默认为 .,即“以后门路”。

函数返回值是一个列表,其中各元素均为字符串,别离是各路径名和文件名。

通常在须要遍历某个文件夹中文件的场景下极为实用。

比方定义以下函数:

import os
def get_filelists(file_dir='.'):
    list_directory = os.listdir(file_dir)
    filelists = []
    for directory in list_directory:
        # os.path 模块稍后会讲到
        if os.path.isfile(directory):
            filelists.append(directory)
    return filelists

该函数的返回值就是当前目录下所有文件而非文件夹的名称列表。

2.5 os.mkdir()

mkdir,即 make directory,用途是 新建一个门路。须要传入一个类门路参数用以指定新建门路的地位和名称,如果指定门路已存在,则会抛出 FileExistsError 异样。

该函数只能在已有的门路下新建一级门路,否则(即新建多级门路)会抛出 FileNotFoundError 异样。

相应地,在须要新建多级门路的场景下,能够应用 os.makedirs() 来实现工作。函数 os.makedirs() 执行的是递归创立,若有必要,会别离新建指定门路通过的两头门路,直到最初创立出末端的“叶子门路”。

示例一:

>>> os.mkdir("test_os_mkdir")
>>> os.mkdir("test_os_mkdir")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileExistsError: [WinError 183] 当文件已存在时,无奈创立该文件。: 'test_os_mkdir'
>>> 
>>> os.mkdir("test_os_mkdir/test_os_makedirs/just/do/python/hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 零碎找不到指定的门路。: 'test_os_mkdir/test_os_makedirs/just/do/python/hello'
>>> 
>>> os.makedirs("test_os_mkdir/test_os_makedirs/just/do/python/hello")

示例二:

In [1]: import os

In [2]: os.getcwd()
Out[2]: 'D:\\Curriculum-development\\ 应用 Python 实现办公自动化 \\Coder\\02- 文件操作 \\OS_Module_Code'

In [3]: for path in os.walk('.'):
   ...:     print(path)
   ...:
('.', ['Tester2Folder', 'TesterFolder'], ['OS-AlexSmith_2021 - 正本 (2).txt', 'OS-AlexSmith_2021 - 正本 (3).txt', 'OS-AlexSmith_2021 - 正本.txt', 'OS-AlexSmith
_2021.txt','OS-I_Have_a_Dream - 正本 (2).txt','OS-I_Have_a_Dream - 正本.txt','OS-I_Have_a_Dream.txt','OS-WordCount_Basic - 正本 (2).py','OS-WordCount_Basi
c - 正本.py','OS-WordCount_Basic.py','OS_Page.py'])
('.\\Tester2Folder', ['Tester2Folder_test'], ['Tester2Folder-AlexSmith_2021 - 正本 (2).txt', 'Tester2Folder-AlexSmith_2021 - 正本 (3).txt', 'Tester2Folder-Alex
Smith_2021 - 正本 (4).txt','Tester2Folder-AlexSmith_2021 - 正本.txt','Tester2Folder-AlexSmith_2021.txt','Tetser2-WordCount_Basic.py'])
('.\\Tester2Folder\\Tester2Folder_test', [], [])
('.\\TesterFolder', [], ['TesterFolder-I_Have_a_Dream - 正本.txt', 'TesterFolder-I_Have_a_Dream.txt', 'TesterFolder-Tester-I_Have_a_Dream - 正本 (2).txt', 'Tes
terFolder-Tester-I_Have_a_Dream - 正本 (3).txt','TesterFolder-WordCount_Basic.py'])

In [4]: os.mkdir("aiyc")

In [5]: for path in os.walk('.'):
   ...:     print(path)
   ...:
('.', ['aiyc', 'Tester2Folder', 'TesterFolder'], ['OS-AlexSmith_2021 - 正本 (2).txt', 'OS-AlexSmith_2021 - 正本 (3).txt', 'OS-AlexSmith_2021 - 正本.txt', 'OS-A
lexSmith_2021.txt','OS-I_Have_a_Dream - 正本 (2).txt','OS-I_Have_a_Dream - 正本.txt','OS-I_Have_a_Dream.txt','OS-WordCount_Basic - 正本 (2).py','OS-WordCo
unt_Basic - 正本.py','OS-WordCount_Basic.py','OS_Page.py'])
('.\\aiyc', [], [])
('.\\Tester2Folder', ['Tester2Folder_test'], ['Tester2Folder-AlexSmith_2021 - 正本 (2).txt', 'Tester2Folder-AlexSmith_2021 - 正本 (3).txt', 'Tester2Folder-Alex
Smith_2021 - 正本 (4).txt','Tester2Folder-AlexSmith_2021 - 正本.txt','Tester2Folder-AlexSmith_2021.txt','Tetser2-WordCount_Basic.py'])
('.\\Tester2Folder\\Tester2Folder_test', [], [])
('.\\TesterFolder', [], ['TesterFolder-I_Have_a_Dream - 正本.txt', 'TesterFolder-I_Have_a_Dream.txt', 'TesterFolder-Tester-I_Have_a_Dream - 正本 (2).txt', 'Tes
terFolder-Tester-I_Have_a_Dream - 正本 (3).txt','TesterFolder-WordCount_Basic.py'])

In [6]: os.mkdir("aiyc")
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-6-53b10652ea17> in <module>
----> 1 os.mkdir("aiyc")

FileExistsError: [WinError 183] 当文件已存在时,无奈创立该文件。: 'aiyc'

In [7]: os.mkdir("aiyc/blog/PythonCourse")
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-7-50d273e0ff25> in <module>
----> 1 os.mkdir("aiyc/blog/PythonCourse")

FileNotFoundError: [WinError 3] 零碎找不到指定的门路。: 'aiyc/blog/PythonCourse'

In [8]: os.makedirs("aiyc/blog/PythonCourse")

In [9]: for path in os.walk('.'):
   ...:     print(path)
   ...:
('.', ['aiyc', 'Tester2Folder', 'TesterFolder'], ['OS-AlexSmith_2021 - 正本 (2).txt', 'OS-AlexSmith_2021 - 正本 (3).txt', 'OS-AlexSmith_2021 - 正本.txt', 'OS-A
lexSmith_2021.txt','OS-I_Have_a_Dream - 正本 (2).txt','OS-I_Have_a_Dream - 正本.txt','OS-I_Have_a_Dream.txt','OS-WordCount_Basic - 正本 (2).py','OS-WordCo
unt_Basic - 正本.py','OS-WordCount_Basic.py','OS_Page.py'])
('.\\aiyc', ['blog'], [])
('.\\aiyc\\blog', ['PythonCourse'], [])
('.\\aiyc\\blog\\PythonCourse', [], [])
('.\\Tester2Folder', ['Tester2Folder_test'], ['Tester2Folder-AlexSmith_2021 - 正本 (2).txt', 'Tester2Folder-AlexSmith_2021 - 正本 (3).txt', 'Tester2Folder-Alex
Smith_2021 - 正本 (4).txt','Tester2Folder-AlexSmith_2021 - 正本.txt','Tester2Folder-AlexSmith_2021.txt','Tetser2-WordCount_Basic.py'])
('.\\Tester2Folder\\Tester2Folder_test', [], [])
('.\\TesterFolder', [], ['TesterFolder-I_Have_a_Dream - 正本.txt', 'TesterFolder-I_Have_a_Dream.txt', 'TesterFolder-Tester-I_Have_a_Dream - 正本 (2).txt', 'Tes
terFolder-Tester-I_Have_a_Dream - 正本 (3).txt','TesterFolder-WordCount_Basic.py'])

In [10]:

2.6 os.remove()

用于删除文件,如果指定门路是目录而非文件的话,就会抛出 IsADirectoryError 异样。删除目录应该应用 os.rmdir() 函数。

同样的,对应于 os.makedirs(),删除门路操作 os.rmdir() 也有一个递归删除的函数 os.removedirs(),该函数会尝试从最上级目录开始,逐级删除指定的门路,简直就是一个 os.makedirs() 的逆过程;一旦遇到非空目录即进行。

In [10]: os.removedirs("aiyc/blog/PythonCourse/") # 我手动在 blog 文件夹中创立了一个文件

In [11]: os.removedirs("aiyc/blog")
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-12-271d0185833e> in <module>
----> 1 os.removedirs("aiyc/blog")

c:\users\clela\appdata\local\programs\python\python38\lib\os.py in removedirs(name)
    239
    240     """
--> 241     rmdir(name)
    242     head, tail = path.split(name)
    243     if not tail:

OSError: [WinError 145] 目录不是空的。: 'aiyc/blog'

2.7 os.rename()

该函数的作用是将文件或门路重命名,个别调用格局为 os.rename(src, dst),行将 src 指向的文件或门路重命名为 dst 指定的名称。

留神, 如果指定的指标门路在其余目录下,该函数还可实现文件或门路的 “剪切并粘贴” 性能。

但无论间接原地重命名还是“剪切粘贴”,两头门路都必须要存在,否则就会抛出 FileNotFoundError 异样。如果指标门路已存在,Windows 下会抛出 FileExistsError 异样;Linux 下,如果指标门路为空且用户权限容许,则会静默笼罩原门路,否则抛出 OSError 异样,

和上两个函数一样,该函数也有对应的递归版本 os.renames(),可能创立缺失的两头门路。

留神,这两种状况下,如果函数执行胜利,都会调用 os.removedir() 函数来递归删除源门路的最上级目录。

看不懂?没事的,我也看不懂!哈哈哈哈哈哈哈哈哈!然而,我来用个小例子给你看懂吧!

咱们当初应用此门路:C:\Users\clela\Desktop\aiyc,该门路下有如下文件:

命令行显示如下:

In [1]: pwd
Out[1]: 'C:\\Users\\clela\\Desktop\\aiyc'

In [2]: ls
 驱动器 C 中的卷是 OS
 卷的序列号是 0AED-8BC3

 C:\Users\clela\Desktop\aiyc 的目录

2021/09/27  21:08    <DIR>          .
2021/09/27  21:08    <DIR>          ..
2021/09/27  19:05         2,183,368 1.2 恐龙乐园.pptx
2021/08/30  09:11           772,010 1.2 恐龙乐园.sb3
               2 个文件      2,955,378 字节
               2 个目录 161,160,978,432 可用字节

In [3]:

接下来,咱们就来操作一波。第一波,批改文件名称:

重命名:

  1. 原文件门路:
C:\\Users\\clela\\Desktop\\aiyc\\1.2 恐龙乐园.pptx
  1. 重新命名文件并且指向同一个门路:
C:\\Users\\clela\\Desktop\\aiyc\\1.2 重新命名.pptx
  1. 应用的代码如下:
In [1]: pwd
Out[1]: 'C:\\Users\\clela\\Desktop\\aiyc'

In [2]: import os

In [3]: path_one = "C:\\Users\\clela\\Desktop\\aiyc\\1.2 恐龙乐园.pptx"

In [4]: path_two = "C:\\Users\\clela\\Desktop\\aiyc\\1.2 重新命名.pptx"

In [5]: os.rename(path_one, path_two)

咱们能够关上能够看到,名称曾经胜利批改了。

In [6]: ls
 驱动器 C 中的卷是 OS
 卷的序列号是 0AED-8BC3

 C:\Users\clela\Desktop\aiyc 的目录

2021/09/28  15:41    <DIR>          .
2021/09/28  15:41    <DIR>          ..
2021/08/30  09:11           772,010 1.2 恐龙乐园.sb3
2021/09/27  19:05         2,183,368 1.2 重新命名.pptx
               2 个文件      2,955,378 字节
               2 个目录 159,386,759,168 可用字节

In [7]:

那下面所说的挪动文件呢?

挪动文件:

  1. 原文件门路:
C:\\Users\\clela\\Desktop\\aiyc\\1.2 重新命名.pptx
  1. 新门路:
C:\\Users\\clela\\Desktop\\aiyc_book\\1.2 重新命名.pptx
  1. 应用的代码:
In [7]: path_one = "C:\\Users\\clela\\Desktop\\aiyc\\1.2 重新命名.pptx"

In [8]: path_two = "C:\\Users\\clela\\Desktop\\aiyc_book\\1.2 重新命名.pptx"

In [9]: os.rename(path_one, path_two)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-9-2390249a0f17> in <module>
----> 1 os.rename(path_one, path_two)

FileNotFoundError: [WinError 3] 零碎找不到指定的门路。: 'C:\\Users\\clela\\Desktop\\aiyc\\1.2 从新命
名.pptx'->'C:\\Users\\clela\\Desktop\\aiyc_book\\1.2 重新命名.pptx'

下面的代码无奈应用,因为以后 aiyc_book 这个文件夹是不存在的。

当然,你能够手动创立文件夹而后运行下面的代码。然而这样显然就违反了自动化办公的初心,所以咱们能够应用 os.renames() 函数来实现。

In [12]: os.renames(path_one, path_two)

2.8 os.getcwd()

“getcwd”实际上是“get the current working directory”的简写,顾名思义,也就是说这个函数的作用是“获取当前工作门路”。在程序运行的过程中,无论物理上程序在理论存储空间的什么中央,“当前工作门路”即可认为是程序所在门路;与之相干的“相对路径”、“同目录下模块导入”等相干的操作均以“当前工作门路”为准。

在交互式环境中,返回的就是交互终端关上的地位;而在 Python 文件中,返回的则是文件所在的地位。

在 Windows 下会有如下输入:

In [13]: os.getcwd()
Out[13]: 'C:\\Users\\clela\\Desktop\\aiyc'

Linux 下的输入则是:

In [1]: import os

In [2]: os.getcwd()
Out[2]: '/home/aiyc/ 桌面'

2.9 os.chdir()

“chdir”其实是“change the directory”的简写,因而 os.chdir() 的用途实际上是切换当前工作门路为指定门路。其中“指定门路”须要作为参数传入函数os.chdir(),该参数既能够是文本或字节型字符串,也能够是一个文件描述符,还能够是一个狭义的类门路(path-like)对象。若指定门路不存在,则会抛出 FileNotFoundError 异样。

在 Windows 下,调用该函数的成果为:

In [13]: os.getcwd()
Out[13]: 'C:\\Users\\clela\\Desktop\\aiyc'

In [14]: os.chdir("C:\\Users\\clela\\Desktop")

In [15]: pwd
Out[15]: 'C:\\Users\\clela\\Desktop'

In [16]: os.getcwd()
Out[16]: 'C:\\Users\\clela\\Desktop'

在 Linux 下的成果则是:

In [1]: import os

In [2]: os.getcwd()
Out[2]: '/home/aiyc/ 桌面'

In [3]: os.chdir("/home/aiyc")

In [4]: os.getcwd()
Out[4]: '/home/aiyc'

In [5]: os.chdir("..") # 也可将参数指定为 "..",即可切换到父目录

In [6]: os.getcwd()
Out[6]: '/home'

有了这个函数,跨目录读写文件和调用模块就会变得十分不便了,很多时候也就不用再重复将同一个文件在各个目录之间复制粘贴运行,脚本齐全能够坐镇中军,在一个目录下实现对其余目录文件的操作,正所谓“运筹帷幄之中,决胜于千里之外”也。

举例来说,能够通过将“当前工作目录”切换到父目录,从而间接拜访父目录的文件内容:

In [9]: import os

In [10]: os.getcwd()
Out[10]: 'D:\\Curriculum-development\\ 应用 Python 实现办公自动化 \\Coder\\02- 文件操作 \\OS_Module_Code\\TesterFolder'

In [11]: os.chdir("..")

In [12]: os.getcwd()
Out[12]: 'D:\\Curriculum-development\\ 应用 Python 实现办公自动化 \\Coder\\02- 文件操作 \\OS_Module_Code'

In [13]: with open("hello_aiyc.txt", "r", encoding="utf-8") as f:
    ...:     print(f.read())
    ...:
欢送拜访 aiyc.com,一起学习 Python 技术~

In [14]: os.listdir()
Out[14]:
['aiyc',
 'hello_aiyc.txt',
 'OS-AlexSmith_2021 - 正本 (2).txt',
 'OS-AlexSmith_2021 - 正本 (3).txt',
 'OS-AlexSmith_2021 - 正本.txt',
 'OS-AlexSmith_2021.txt',
 'OS-I_Have_a_Dream - 正本 (2).txt',
 'OS-I_Have_a_Dream - 正本.txt',
 'OS-I_Have_a_Dream.txt',
 'OS-WordCount_Basic - 正本 (2).py',
 'OS-WordCount_Basic - 正本.py',
 'OS-WordCount_Basic.py',
 'OS_Page.py',
 'Tester2Folder',
 'TesterFolder',
 '__pycache__']

3. os.path 模块

其实这个模块是 os 模块依据零碎类型从另一个模块导入的,并非间接由 os 模块实现,比方 os.name 值为 nt,则在 os 模块中执行 import ntpath as path;如果 os.name 值为 posix,则导入posixpath

应用该模块要留神一个很重要的个性:os.path 中的函数基本上是纯正的字符串操作。换句话说,传入该模块函数的参数甚至不须要是一个无效门路,该模块也不会试图拜访这个门路,而仅仅是依照“门路”的通用格局对字符串进行解决。

更进一步地说,os.path 模块的性能咱们都能够本人应用字符串操作手动实现,该模块的作用是让咱们在实现雷同性能的时候不用思考具体的零碎,尤其是不须要过多关注文件系统分隔符的问题。

3.1 os.path.join()

这是一个非常实用的函数,能够将多个传入门路组合为一个门路。实际上是将传入的几个字符串用零碎的分隔符连接起来,组合成一个新的字符串,所以个别的用法是将第一个参数作为父目录,之后每一个参数即便下一级目录,从而组合成一个新的合乎逻辑的门路。

但如果传入门路中存在一个“绝对路径”格局的字符串,且这个字符串不是函数的第一个参数,那么其余在这个参数之前的所有参数都会被抛弃,余下的参数再进行组合。更精确地说,只有最初一个“绝对路径”及其之后的参数才会体现在返回后果中。

In [16]: os.path.join("aiyc", "do", "python", "dot", "top")
Out[16]: 'aiyc\\do\\python\\dot\\top'

In [17]: os.path.join("aiyc", "do", "C:/", "python", "dot", "top")
Out[17]: 'C:/python\\dot\\top'

In [18]: os.path.join("aiyc", "do", "d:/", "python", "dot", "g:/", "top")
Out[18]: 'g:/top'

3.2 os.path.abspath()

将传入门路规范化,返回一个相应的绝对路径格局的字符串。

也就是说当传入门路合乎“绝对路径”的格局时,该函数仅仅将门路分隔符替换为适应以后零碎的字符,不做其余任何操作,并将后果返回。所谓“绝对路径的格局”,其实指的就是一个字母加冒号,之后跟分隔符和字符串序列的格局:

In [23]: os.path.abspath("a:/aiyc/do/python") # 我的零碎中并没有 a 盘
Out[23]: 'a:\\aiyc\\do\\python'

In [24]: os.path.abspath("a:/aiyc/do//python")
Out[24]: 'a:\\aiyc\\do\\python'

In [25]: os.path.abspath("a:/aiyc/do//////python")
Out[25]: 'a:\\aiyc\\do\\python'

当指定的门路不合乎上述格局时,该函数会主动获取当前工作门路,并应用os.path.join() 函数将其与传入的参数组合成为一个新的门路字符串。示例如下:

In [28]: os.getcwd()
Out[28]: 'D:\\Curriculum-development\\ 应用 Python 实现办公自动化 \\Coder\\02- 文件操作 \\OS_Module_Code'

In [29]: os.path.abspath("Python_online/aiyc")
Out[29]: 'D:\\Curriculum-development\\ 应用 Python 实现办公自动化 \\Coder\\02- 文件操作 \\OS_Module_Code\\Python_online\\aiyc'

3.3 os.path.basename()

该函数返回传入门路的“基名”,即传入门路的最上级目录。

In [31]: os.path.basename("D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Code") # 我的零碎中同样没有这么一个门路。可见 os.path.basename() 页是单纯进行字符串解决
Out[31]: 'OS_Module_Code'

整这个函数要留神的一点是,返回的“基名”实际上是传入门路最初一个分隔符之后的子字符串,也就是说,如果最上级目录之后还有一个分隔符,失去的就会是一个空字符串:

In [33]: os.path.basename("D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Code\\")
Out[33]: ''

3.4 os.path.dirname()

与上一个函数正好相同,返回的是最初一个分隔符前的整个字符串:

In [35]: os.path.dirname("D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Code")
Out[35]: 'D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作'

In [36]: os.path.dirname("D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Code\\")
Out[36]: 'D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Code'

3.5 os.path.split()

哈哈实际上前两个函数都是弟弟,这个函数才是老大。

函数 os.path.split() 的性能就是将传入门路以最初一个分隔符为界,分成两个字符串,并打包成元组的模式返回;

前两个函数 os.path.dirname()os.path.basename() 的返回值别离是函数 os.path.split() 返回值的第一个、第二个元素。

就连二者的具体实现都非常实在:

Signature: os.path.dirname(p)
Source:
def dirname(p):
    """Returns the directory component of a pathname"""
    return split(p)[0]
File:      c:\users\clela\appdata\local\programs\python\python38\lib\ntpath.py
Type:      function

Signature: os.path.basename(p)
Source:
def basename(p):
    """Returns the final component of a pathname"""
    return split(p)[1]
File:      c:\users\clela\appdata\local\programs\python\python38\lib\ntpath.py
Type:      function

通过 os.path.join() 函数又能够把它们组合起来失去原先的门路。

3.6 os.path.exists() 门路是否存在

这个函数用于判断门路所指向的地位是否存在。若存在则返回 True,不存在则返回 False

In [41]: os.path.exists(".")
Out[41]: True

In [42]: os.path.exists("D:\\Curriculum-development\\aiyc_lesson\\Coder\\02- 文件操作 \\OS_Module_Cod") # 不存在的门路
Out[42]: False

In [43]: os.path.exists("D:\\Curriculum-development\\")
Out[43]: True

个别的用法是在须要长久化保留某些数据的场景,为防止反复创立某个文件,须要在写入前用该函数检测一下相应文件是否存在,若不存在则新建,若存在则在文件内容之后减少新的内容。

3.7 os.path.isabs()

该函数判断传入门路是否是绝对路径,若是则返回 True,否则返回 False。当然,仅仅是检测格局,同样不对其有效性进行任何核验:

In [46]: os.path.isabs(".")
Out[46]: False

In [47]: os.path.isabs("D:\\Curriculum-development")
Out[47]: True

3.8 os.path.isfile() 和 os.path.isdir()

这两个函数别离判断传入门路是否是文件或门路,留神,此处会核验门路的有效性,如果是有效门路将会继续返回 False

In [54]: # 有效门路

In [55]: os.path.isfile("a:/aiycpython")
Out[55]: False

In [56]: # 无效门路

In [57]: os.path.isfile("OS-AlexSmith_2021.txt")
Out[57]: True

In [58]: # 有效门路

In [59]: os.path.isdir("D:\\Curriculum-development\\aiyc")
Out[59]: False

In [60]: # 无效门路

In [61]: os.path.isdir("D:\\Curriculum-development")
Out[61]: True

4. 总结

本文具体介绍了与操作系统交互的 os 模块中一些罕用的属性和函数,根本能够笼罩初阶的学习和应用。有了这些性能,咱们曾经能够写出一些比拟实用的脚本了。

除了文中介绍的函数外,os 模块还有很多更加简单的性能,但大多是咱们临时用不到的,当前用到会进一步解说。

AI 悦创·推出辅导班啦,包含「Python 语言辅导班、C++ 辅导班、算法 / 数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 安排作业 + 我的项目实际等。QQ、微信在线,随时响应!V:Jiabcdefh

退出移动版