美文网首页
Python3 CookBook学习笔记 -- 文件与IO

Python3 CookBook学习笔记 -- 文件与IO

作者: faris_shi | 来源:发表于2018-03-03 00:54 被阅读10次

    1. 读写文本数据

    打开一个文本文件:open('somefile.txt', model),需要注意:

    • 文件的读写操作默认使用系统编码, 如果你想指定文件编码:open('somefile.txt', 'rt', encoding='latin-1')

    • r代表读取文件、t代表文本文件、w代表重新写入文件、a代表追加文件

    • 换行符的识别问题,在Unix和Windows中是不一样的(分别是 \n\r\n )。 默认情况下,Python会以统一模式处理换行符。 这种模式下,在读取文本的时候,Python可以识别所有的普通换行符并将其转换为单个 \n 字符。如果你不希望这种默认的处理方式,可以给 open() 函数传入参数 newline=''

    >>> f = open('hello.txt', 'rt')
    >>> f.read()
    'hello world!\n'
    >>> 
    >>> g = open('hello.txt', 'rt', newline='')
    >>> g.read()
    'hello world!\r\n'
    
    • 关闭文件问题,我们可以使用with语句来完成文件的自动关闭,否则需要手动关闭
    >>> with open('somefile.txt', 'wt') as f:
    ...     print("hello world", file=f)
    ... 
    >>> f = open('/Users/faris/Desktop/somefile.txt', 'wt')
    >>> f.write("hello world")
    11
    >>> f.close()
    

    2. 打印

    print 的方法定义如下:

    def print(self, *args, sep=' ', end='\n', file=None)
    

    我们可以对print方法传入多个值。

    >>> print(1,2,3,4,5)
    1 2 3 4 5
    

    同时我们可以通过设定 分隔符与结束符来控制打印效果。

    >>> print(1,2,3,4,5, sep=',')
    1,2,3,4,5
    >>> print(1,2,3,4,5, sep=',', end='##\n')
    1,2,3,4,5##
    >>> 
    

    当我们想用非空格符打印一个序列时:有人会想到 str.join()

    >>> print(','.join(('ACME','50','91.5')))
    ACME,50,91.5
    >>> 
    

    但是 str.join()仅仅适用于字符串序列。这意味着你通常需要执行另外一些转换才能让它正常工作。

    >>> print(','.join(str(x) for x in row))
    ACME,50,91.5
    >>> 
    
    >>> print(*row, sep=',')
    ACME,50,91.5
    >>>
    

    两种代码的简洁与效率一目了然。

    3. 读写字节数据

    我们使用模式为 rbwbopen() 函数来读取或写入二进制数据

    在读取二进制数据时,需要指明的是所有返回的数据都是字节字符串格式的,而不是文本字符串。

    在写入的时候,必须保证参数是以字节形式对外暴露数据的对象(比如字节字符串,字节数组对象等)。

    >>> with open('somefile.bin', 'wb') as f:
    ...     f.write(b'Hello World')
    ... 
    11
    >>> with open('somefile.bin', 'rb') as f:
    ...     print(f.read())
    ... 
    b'Hello World'
    

    如果你想从二进制模式的文件中读取或写入文本数据,必须确保要进行解码和编码操作。比如:

    >>> with open('somefile.bin', 'wb') as f:
    ...     f.write('Hello World'.encode("UTF-8"))
    ... 
    11
    >>> 
    >>> 
    >>> 
    >>> with open('somefile.bin', 'rb') as f:
    ...     data=f.read()
    ...     print(data.decode("UTF-8"))
    ... 
    Hello World
    

    4. 文件不存在才能写入

    向一个文件中写入数据,但是前提必须是这个文件在文件系统上不存在。 也就是不允许覆盖已存在的文件内容。

    可以在 open() 函数中使用 x 模式来代替 w 模式的方法来解决这个问题。

    5. 读写压缩文件

    如何读写一个gzip或bz2格式的压缩文件:

    >>> import gzip
    >>> import bz2
    >>> 
    >>> with gzip.open('somefile.gz', 'wt') as f:
    ...     f.write("Hello world gz")
    ... 
    14
    >>> with gzip.open('somefile.gz', 'rt') as f:
    ...     print(f.read())
    ... 
    Hello world gz
    >>> 
    >>> with bz2.open('somefile.bz2', 'wt') as f:
    ...     f.write("Hello world bz2")
    ... 
    15
    >>> with bz2.open('somefile.bz2', 'rt') as f:
    ...     print(f.read())
    ... 
    Hello world bz2
    

    可以看出基本上与 open() 的用法一致,也与 open 有一样的参数,如:encodingnewline

    以上所有的I/O操作都使用文本模式并执行 Unicode 的编码/解码。 类似的,如果你想操作二进制数据,使用 rb 或者 wb 文件模式即可。

    当然在写数据时还可以指定 压缩等级 compresslevel:

    with gzip.open('/Users/faris/Desktop/somefile.gz', 'wt', compresslevel=5) as f:
    

    这两个写文件的操作还可以用在任何以二进制打开的文件或者类文件上(如:套接字,管道和内存)。

    >>> f = open('/Users/faris/Desktop/somefile.gz', 'rb')
    >>> with gzip.open(f, 'rt') as g:
    ...     print(g.read())
    ... 
    Hello world gz
    

    6. 读取二进制数据到可变缓冲区中

    你想直接读取二进制数据到一个可变缓冲区中,而不需要做任何的中间复制操作。 或者你想原地修改数据并将它写回到一个文件中去。

    为了读取数据到一个可变数组中,使用文件对象的 readinto() 方法。

    >>> import os.path
    >>> 
    >>> def read_into_buffer(filename):
    ...     buf = bytearray(os.path.getsize(filename))
    ...     with open(filename, 'rb') as f:
    ...             f.readinto(buf)
    ...     return buf
    ... 
    >>> filename="/Users/faris/Desktop/a.txt"
    >>> with open(filename, 'wb') as f:
    ...     f.write(b'Hello World')
    ... 
    11
    >>> 
    >>> buf = read_into_buffer(filename)
    >>> print(buf)
    bytearray(b'Hello World')
    

    7. 文件路径名的操作

    你需要使用路径名来获取文件名,目录名,绝对路径等等。

    >>> import os
    >>> path="/Users/faris/Desktop/a.txt" 
    >>> os.path.basename(path)
    'a.txt'
    >>> 
    >>> os.path.dirname(path)
    '/Users/faris/Desktop'
    >>> 
    >>> os.path.join('tmp', 'data', os.path.basename(path))
    'tmp/data/a.txt'
    >>> 
    >>> os.path.splitext(path)
    ('/Users/faris/Desktop/a', '.txt')
    >>> 
    >>> path='~/Desktop/a.txt'
    >>> os.path.expanduser(path)
    '/Users/faris/Desktop/a.txt'
    

    由于操作系统的差异,导致文件表示上面会有很多的差异。而我们为了程序上可移植性考虑,对于文件路径的操作,应该尽可能的使用os.path

    8. 测试文件是否存在

    测试文件是否存在:

    >>> import os
    >>> os.path.exists('/etc/passwd')
    True
    >>> os.path.exists('/tmp/spam')
    False
    >>>
    

    判断文件类型:

    >>> # Is a regular file
    >>> os.path.isfile('/etc/passwd')
    True
    >>> # Is a directory
    >>> os.path.isdir('/etc/passwd')
    False
    >>> # Is a symbolic link
    >>> os.path.islink('/usr/local/bin/python3')
    True
    >>> # Get the file linked to
    >>> os.path.realpath('/usr/local/bin/python3')
    '/usr/local/bin/python3.3'
    >>>
    

    获取文件元数据:

    >>> os.path.getsize('/etc/passwd')
    3669
    >>> os.path.getmtime('/etc/passwd')
    1272478234.0
    >>> import time
    >>> time.ctime(os.path.getmtime('/etc/passwd'))
    'Wed Apr 28 13:10:34 2010'
    >>>
    

    9. 获取文件夹中的文件列表

    使用 os.listdir() 函数来获取某个目录中的文件列表:

    >>> import os
    >>> a=os.listdir('somedir')
    >>> print(*a, sep='\n')
    .DS_Store
    .localized
    aaaaaa.png
    adadsf.png
    asdfas.png
    bbbbb.png
    cccccc.png
    docker.txt
    fffff.png
    gggg.png
    RedBlack.pdf
    

    相关文章

      网友评论

          本文标题:Python3 CookBook学习笔记 -- 文件与IO

          本文链接:https://www.haomeiwen.com/subject/pbjoxftx.html