《Python编程》笔记(三)

来源:互联网 发布:8090端口 编辑:程序博客网 时间:2024/06/15 07:26

文件和目录工具

  • open函数被调用时将返回一个新的与外部相连的文件对象。这个文件对象有一些方法,可以与文件双向传输数据,并且能够执行多种文件相关的操作。
  • Python 3.X对含有文本的文件和二进制数据做出了区分:

    • 文本文件含有Unicode文本。文件默认执行换行符自动转换,而且自动将Unicode编码应用于文件内容:它们在文件进行双向传输时按照一个给定或默认的编码名称,对原始二进制字节进行编码和解码。编码对于ASCII文本很简单,但在其他情况下可能比较复杂。
    • 二进制文件包含原始的8位字节。二进制文本文件的内容始终是一个字节字符串,通常是一个字节对象——小整数构成的序列,支持大多数str操作并尽量显示为ASCII字符。二进制文件与其他文件进行双向传输时不会进行换行符转换和Unicode编码。
  • 实践中,文本文件用于所有真正的文本相关数据,而二进制文件则用于储存内容,如打包的二进制数据、图像、音频文件和可执行文件等。在对编码新文件内容时,对文本使用普通字符串(如spam或者bytes.decode())而对二进制使用字节字符串(如bspam或str.encode())。

  • open函数返回的对象常用的方法:

    • 读取:read, readline, readlines
    • 写入:write, writelines
    • 释放:close
    • 移动:seek
    • 强制转移到磁盘:flush
    • 获取底层文件句柄:fileno
  • 内建文件对象操作:

    • 打开:如果传入的参数不指定具体路径,将使用当前的工作目录。
    • 写入:write方法写入的就是传入的字符串,而没有附加格式。文本文件写入的数据可能会进行行尾或者Unicode转换,但是这些转换会在数据读取回去的时候得以还原。
    • 关闭:close方法用于释放系统资源。正常情况下,当解释器对文件对象进行垃圾回收时,文件会被自动关闭。所以close调用经常是可选的。比如下面的用法:
      open('file.txt', 'w').write('hello')open('file.txt', 'r').read()
  • 一般来说,关闭文件不仅没有坏处,而且还能形成良好的操作习惯。

  • 使用with语句,可以保证无论出现什么状况,文件对象都能正常关闭。
  • file.seek(0)用于回到文件的起始处。
  • 文件迭代器在处理大型文本文件时比较节省空间,不会一次加载整个文件。迭代器通过__next__方法(由内建函数next运行)逐行获得文本,在遇到文件末尾(EOF)时会得到空字符串,可以抛出一个异常结束迭代。
  • 在所有迭代情境下,迭代器都得以自动使用,包括list构造器调用,列表解析表达式,map调用,以及in成员关系检查。
>>> list(open('file.txt'))['Happy, hello\n', 'Good\n', 'Yes\n', 'Why?\n', "Realy? I'm not in good mood.\n"]>>> lines = [l.upper() for l in open('file.txt')]>>> lines['HAPPY, HELLO\n', 'GOOD\n', 'YES\n', 'WHY?\n', "REALY? I'M NOT IN GOOD MOOD.\n"]>>> list(map(str.split, open('file.txt')))[['Happy,', 'hello'], ['Good'], ['Yes'], ['Why?'], ['Realy?', "I'm", 'not', 'in', 'good', 'mood.']]
  • 三个重要的open参数:

    • file:指定显示目录,或者文件名(会自动使用CWD)
    • mode
    • r:打开并读取(默认)
    • w:打开用于写入,会清除原先的文件内容
    • a:追加
    • x:创建新文件并打开等待写入
    • b:二进制模式
    • t:文本模式(默认)
    • +:通常于文件对象seek方法联合使用,实现随机的读取和写入权限
    • buffering:0表示文件操作是无缓冲的(数据会立即传输,只允许在二进制 模式下使用),1表示是逐行缓冲的,传入其他任意正值则表示全缓冲(默认设置)
  • 在所有情况下,文件与程序之间传输的数据,即使是二进制数据,在脚本中还是表示为Python字符串。然而对于二进制模式文件,文件内容则表示为字节字符串。

  • 对外部文件进行双向传输时,文本模式的文件对象通常根据默认或指定的Unicode编码类型来转换数据,这些内容在文件里是编码后的形式,在内存中则是解码后的形式。二进制模式文件不进行这些转换。

  • 编码只与文件中的字符串有关,字符串一旦载入内存就成了简单的Unicode字符序列(码点)。
  • 在类Unix系统上,行尾是\n;Windows上却是两个字符\r\n表示行尾。
  • 在Python 3.X中,不论如何都无法以文本模式处理二进制数据,处理文本模式对文件内容自动应用Unicode编码,所以如果数据在输入时无法解码或输出时无法编码都会产生失败。使用二进制模式可以避免Unicode错误,也会自动禁止换行符转换。
  • struct模块:提供了用于打包和解压二进制数据的调用,能够用你想用的任何一种字节来进行组合和分解(字节序决定了二进制数字的最高有效位是居左还是居右)。pack用于打包,unpack用于解包。
  • seek允许接受第二种参数,决定偏移的方式:

    • 0:表示绝对文件位置(默认)
    • 1:表示寻找的是基于当前所在的相对位置
    • 2:表示寻求基于文件结尾的相对位置
  • 一般情况下,seek支持基于字节偏移的随机访问。如,可以在二进制文件中寻找一个记录大小的倍数,允许通过其相对位置获取一个记录。

  • open函数中,模式r+b允许写入和读取,初始化时不会清除文档内容;w+b也允许写入和读取,但是会清空文档内容。它们和seek()配合可以实现随机访问。
  • os模块中的底层文件工具:

    • os.open(path, flags, mode):打开文件并返回描述符
    • os.read(descriptor, N):最多读取N个字节并返回一个字节字符串
    • os.write(descriptor, string):把字节字符串string中的字节写入文件
    • os.lseek(descriptor, position, how):在文件中移至position
  • 内建的文件对象和os模块的描述符文件由不同 的工具集处理,但是其实相互之间是有联系的,文件对象所使用的文件系统就仅仅在基于描述符的文件工具之上添加了一层逻辑所得。

  • fileno文件对象方法返回的整数描述符是与某个内建的文件对象相关联的。
>>> file = open('file.txt', 'w')>>> fd = file.fileno()>>> fd8>>> os.write(fd, b'hello, world')12>>> os.write(fd, b'good')4>>> file.close()>>> file = open('file.txt')>>> file.read()'hello, worldgood'
  • os模块为文件处理提供更多底层控制。内建的open函数受限于所使用的底层文件系统,增加了冗余功能,所以,脚本中使用os模块提供的文件工具可以进行更加精细的控制。
  • os.stat调用返回一个数值组成的元组(带有名称的特殊元组),给出了命名文件底层信息,stat模块通过导出此信息的常量以便在多个平台上查询该信息。不过除了底层的文件查询操作以外,很少用到os.stat
  • 遍历目录:

    • os.popen运行shell命令,缺点是需要使用平台专用的shell,而且需要启动一个独立程序,从而导致性能下降:

      # 运行ls -l命令查看目录for file in os.popen('ls -l /etc'): print(file)
    • 对于管道对象,迭代器的效果比简单地避免一次性将整个结果加载到内存更为有用。比较下面的两种方式:

      # 非阻塞,可以直接看到查找结果>>> for msg in os.popen('find /home/lab -name "*a"'):print(msg[:])# 阻塞模式os.popen('find /home/lab -name "*a"').readlines()
    • glob.glob内建函数接受文件名模式扩展,并返回一个匹配文件名组成的列表(并非生成器)。它接受shell中常用的文件名模式语法:?代表单个字符,*代表任意字符,[]括起来的是字符选集。它的可移植性更好,虽然也可以通过运行shell命令完成类似的任务。

    • os.listdir调用可以将提供的目录中的文件名收集到一个列表中返回。
  • 遍历目录树:

    • os.walk访问器:用于扫描目录树,顺便在每个目录下面运行我们所提供的代码,被调用时需要指定目录的根名称,然后自动从根目录开始向下遍历整个目录树。在树的每个目录中,它会产生一个包含三个项目的元组(当前目录名称,所有子目录组成的列表,当前目录下所有的文件组成的列表)。
      # 查找目录下所有的文件中含有某个关键字的函数>>> def find_key(keyword, root):for curdir, _, files in os.walk(root):    for f in files:        if f.endswith('py') or f.endswith('sh'):            path = os.path.join(curdir, f)            if keyword in open(path).read():                print("Found {} in {}".format(keyword, path))
0 0
原创粉丝点击