函数使用 (五)

目录管理(os)

  • system:执行系统命令

    1
    2
    # 执行系统命令
    os.system('cls')
  • name:获取操作系统名称

    1
    2
    # 操作系统的名称,nt代表Windows,posix代表Unix
    print(os.name)
  • environ:获取环境变量

    1
    2
    3
    4
    5
    6
    # 获取环境变量
    env = os.environ

    print(env['path'])
    print(env.get('path'))
    print(env.get('HELLO'))
  • getcwd:获取当前工作目录

    1
    2
    # 获取当前工作目录
    print(os.getcwd())
  • mkdir:创建目录,只能是单层目录

    1
    2
    3
    4
    5
    # 创建目录,只能是单层目录
    os.mkdir('hello')

    # 这里会失败
    # os.mkdir('a/b/c')
  • makedirs:创建目录,会创建中间目录:

    1
    2
    # 会创建中间目录
    os.makedirs('a/b/c')
  • rmdir:删除目录,只能删除空目录

    1
    2
    3
    os.rmdir(path)

    # 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
  • remove:删除路径为 path 的文件

    1
    2
    3
    4
    os.remove(path)

    # 删除路径为path的文件。
    # 如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。
  • removedirs:递归删除目录

    1
    2
    3
    os.removedirs(path)

    # 递归删除目录。
  • unlink:删除文件

    1
    2
    3
    os.unlink(path)

    # 删除文件
  • rename:修改文件名(可以是目录)

    1
    2
    3
    4
    5
    # 修改名字(old, new)
    os.rename('a', 'c')

    # 也可以修改文件名
    os.rename('test.py', '123.py')
  • renames:递归重命名

    1
    2
    3
    os.renames(old, new)

    # 递归地对目录进行更名,也可以对文件进行更名。
  • stat:查看文件信息

    1
    2
    # 查看文件信息
    print(os.stat('123.py'))
  • listdir:列出直接子文件

    1
    2
    # 列出直接子文件
    print(os.listdir('c'))
  • 相对目录、绝对目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    相对目录:就是有参考的目录
    . 表示当前目录, 通常 ./ 可以省略
    .. 表示上一级目录
    绝对目录:Windows中以某个盘符开头,类Unix系统中以'/'开头的目录

    目录分隔符:
    类Unix:/
    Windows:/ 或 \
    建议:同一使用'/'表示

    说明:在文件操作时,使用相对目录和绝对目录都可以
  • path

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    from os import path

    # 拼接目录
    print(path.join('abc/def', '123.py'))

    # 提取文件后缀(切割文件名与后缀)
    name, ext = path.splitext('789.py')
    print(name, ext)

    # 提取目录名(最后一个目录分割符前面的内容)
    print(path.dirname('132/456/789.py'))

    # 提取文件名(包括后缀)
    print(path.basename('132/456/789.py'))

    # 切割文件名和目录
    print(path.split('132/456/789.py'))

    # 判断文件是否存在(可以是目录)
    print(path.exists('c'))

    # 判断是否是目录文件
    print(path.isdir('c'))

    # 判断是否是普通文件
    print(path.isfile('123.py'))
  • 练习

    1
    自己实现目录大小的统计,需要使用递归

文件管理

  • 打开文件 (open)

    • 示例:

      1
      fp = open('00-test.txt', 'r', encoding='utf8')
    • 参数:

      1
      2
      3
      参数1:文件路径名
      参数2:打开方式
      参数3:编码格式,通常可以不指定,系统会自动识别处理
    • 打开方式:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      r:只读方式,文件不存在会报错
      w:只写方式,文件不存在创建文件,文件存在清空内容
      a:追加方式,文件不存在则创建,文件存在直接打开(不会清空内容),只能向后追加内容
      r+:在r的方式下添加了写的功能
      w+:在w的方式下添加了读的功能
      a+:在a的方式下添加了读的功能

      在上面的模式上添加b,表示二进制打开方式:rb、wb、ab、rb+、wb+、ab+
      注意:文件的读写数据全部是bytes类型,没有添加b的全部是str类型
    • 注意

      将打开方式设置为 w+ 或 a+ 时,直接进行读操作,得到的内容都是空,但原因不太相同:

      • 如果打开方式设置为 w+,即使没有执行 write 操作,也会将文件内容清空,因此这个时候直接进行读草稿,读到的是空内容;
      • 如果打开方式设置为 a+,文件指针位置默认在最后面,因为读内容时,是按照指针的位置往后读,所以如果指针位置在最后,那读出来的是空,在读之前,一定要注意确认好指针位置是对的;
      • 如果文件打开时无内容,六种方式打开后文件指针的位置都是 0;
      • 如果文件打开时有内容,r/r+/w/w+ 打开后文件指针的位置都是 0,a/a+ 打开后文件指针的位置在末尾,此时可能需先移动文件指针再进行读写操作。
  • 编码方式:

    1
    2
    3
    4
    5
    6
    7
    ASCII:美国信息交换标准代码
    ANSI:拓展的ASCII
    gb2312:中国的ANSI
    gbk:拓展的gb2312

    Unicode:是一套理论,实现方式不限
    UTF-8:可变长度的Unicode实现,对中文的支持比较友好
    1
    2
    3
    4
    # 解码 bytes => str
    print(b'hello'.decode('utf-8'))
    # 编码 str => bytes
    print('hello'.encode('utf-8'))
  • 关闭文件 (close)

    1
    2
    # 关闭文件
    fp.close()
  • 文件的读写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 读取指定长度的内容
    ret = fp.read(3)

    # 写入内容
    fp.write('hello')

    # 读取一行,包括换行
    print(fp.readline())

    # 读取所有行,返回一个列表
    print(fp.readlines())

    # 是否可读
    print(fp.readable())

    # 是否可写
    print(fp.writable())
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    with open('text.txt', 'r', encoding='utf8')as fp:
    # <_io.TextIOWrapper name='text.txt' mode='r' encoding='utf8'>
    print(fp)
    fp.seek(0)
    # fp可以使用for循环遍历,结果和遍历fp.readlines()相同
    for i in fp:
    print(i)
    fp.seek(0)
    print('=' * 60)

    # 读取所有行,返回一个列表,包括换行
    print(fp.readlines()) # ['hello\n', 'world\n', 'really\n']
    fp.seek(0)
    for j in fp.readlines():
    print(j)
    fp.seek(0)
    print('=' * 60)

    # 读取所有内容
    print(fp.read())
    fp.seek(0)
    for k in fp.read():
    print(k)
    fp.seek(0)
    print('=' * 60)

    # 读取一行,包括换行
    print(fp.readline())
    fp.seek(0)
    for m in fp.readline():
    print(m)

    # 运行结果如下
    '''
    <_io.TextIOWrapper name='text.txt' mode='r' encoding='utf8'>
    hello

    world

    really

    ============================================================
    ['hello\n', 'world\n', 'really\n']
    hello

    world

    really

    ============================================================
    hello
    world
    really

    h
    e
    l
    l
    o


    w
    o
    r
    l
    d


    r
    e
    a
    l
    l
    y


    ============================================================
    hello

    h
    e
    l
    l
    o



    '''
    1
    2
    3
    4
    hello
    world
    really

    test.txt

  • 文件指针

    1
    2
    3
    4
    5
    6
    7
    8
    # 返回文件指针的操作位置
    print(fp.tell())

    # 设置偏移
    # 参数1:偏移量
    # 参数2:参考位置,0:开头,1:当前,2:末尾
    # 定位到末尾
    fp.seek(0, 2)

    带 b 的方式 seek 没有异常,不带 b 的时候,相对于当前位置无法偏移,相对于当前位置只能偏移 0

  • 文件删除

    1
    2
    3
    # 删除文件
    import os
    os.remove('02-test.py')
  • with 语句

    • 场景:做文件操作时,中间无论读写,也无论有无异常,最终一定要把文件关闭
    • with:使用 with,不必再关心文件的关闭问题,with 语句块结束后一定会确保文件关闭
      1
      2
      3
      4
      5
      6
      7
      8
      9
      # fp = open('test.txt', 'rb')
      # # 各种读写操作
      # fp.close()

      # 使用with,无需关心文件的关闭问题
      with open('test.txt', 'rb') as fp:
      content = fp.read(5)
      print(content)

练习

  1. 实现一个拷贝文件的功能,提醒:要考虑超大文件问题,如:一次读取 1024 字节,循环读取
  2. 递归删除一个文件夹
  3. 统计一个文件夹的大小
  4. 拷贝一个文件夹
  5. 移动一个文件夹
  6. 目录整理:
    • 一个目录中有各种文件,也有文件夹
    • 将所有的文件夹统一放到 DIR 目录下
    • 将没有后缀的文件同一放到 others 目录下
    • 将有后缀的文件放到后缀名大学的文件夹下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      # 处理前
      test/
      dir1/
      dir2/
      1.py
      2.py
      3.txt
      4.pdf
      123
      456

      # 处理后
      test/
      DIR/
      dir1/
      dir2/
      PY/
      1.py
      2.py
      TXT/
      3.txt
      PDF/
      4.pdf
      OTHERS/
      123
      456

      友情提醒:中间使用的所有文件目录的判断都需要进行拼接。

------------- 本文结束 感谢您的阅读 -------------
正在加载今日诗词....