美文网首页
【Chapter 3.3】Python 的文件以及操作系统《利用

【Chapter 3.3】Python 的文件以及操作系统《利用

作者: 蜘蛛的梦呓 | 来源:发表于2018-05-19 23:03 被阅读0次

    【Chapter 3.3】Python 的文件以及操作系统

    用内建的open函数能打开、读取、写入一个文件,要给open一个相对路径或绝对路径:

    In [207]: path = 'examples/segismundo.txt'
    
    In [208]: f = open(path)
    

    默认情况下,文件是以只读模式('r')打开的。然后,我们就可以像处理列表那样来处理这个文件句柄f了,比如对行进行迭代:

    for line in f:
        pass
    

    从文件中取出的行都带有完整的行结束符(EOL),因此你常常会看到下面这样的代码(得到一组没有EOL的行):

    In [209]: lines = [x.rstrip() for x in open(path)]
    
    In [210]: lines
    Out[210]: 
    ['Sueña el rico en su riqueza,',
     'que más cuidados le ofrece;',
     '',
     'sueña el pobre que padece',
     'su miseria y su pobreza;',
     '',
     'sueña el que a medrar empieza,',
     'sueña el que afana y pretende,',
     'sueña el que agravia y ofende,',
     '',
     'y en el mundo, en conclusión,',
     'todos sueñan lo que son,',
     'aunque ninguno lo entiende.',
     '']
    
    

    如果使用open创建文件对象,一定要用close关闭它。关闭文件可以返回操作系统资源:

    In [211]: f.close()
    

    用with语句可以可以更容易地清理打开的文件:

    In [212]: with open(path) as f:
       .....:     lines = [x.rstrip() for x in f]
    

    这样可以在退出代码块时,自动关闭文件。

    如果输入f =open(path,'w'),就会有一个新文件被创建在examples/segismundo.txt,并覆盖掉该位置原来的任何数据。另外有一个x文件模式,它可以创建可写的文件,但是如果文件路径存在,就无法创建。表3-3列出了所有的读/写模式。

    i

    对于可读文件,一些常用的方法是read、seek和tell。read会从文件返回字符。字符的内容是由文件的编码决定的(如UTF-8),如果是二进制模式打开的就是原始字节:

    In [213]: f = open(path)
    
    In [214]: f.read(10)
    Out[214]: 'Sueña el r'
    
    In [215]: f2 = open(path, 'rb')  # Binary mode
    
    In [216]: f2.read(10)
    Out[216]: b'Sue\xc3\xb1a el '
    

    read模式会将文件句柄的位置提前,提前的数量是读取的字节数。tell可以给出当前的位置:

    In [217]: f.tell()
    Out[217]: 11
    
    In [218]: f2.tell()
    Out[218]: 10
    

    尽管我们从文件读取了10个字符,位置却是11,这是因为用默认的编码用了这么多字节才解码了这10个字符。你可以用sys模块检查默认的编码:

    In [219]: import sys
    
    In [220]: sys.getdefaultencoding()
    Out[220]: 'utf-8'
    

    seek将文件位置更改为文件中的指定字节:

    In [221]: f.seek(3)
    Out[221]: 3
    
    In [222]: f.read(1)
    Out[222]: 'ñ'
    

    最后,关闭文件:

    In [223]: f.close()
    
    In [224]: f2.close()
    

    向文件写入,可以使用文件的write或writelines方法。例如,我们可以创建一个无空行版的prof_mod.py:

    In [225]: with open('tmp.txt', 'w') as handle:
      .....:     handle.writelines(x for x in open(path) if len(x) > 1)
    
    In [226]: with open('tmp.txt') as f:
      .....:     lines = f.readlines()
    
    In [227]: lines
    Out[227]: 
    ['Sueña el rico en su riqueza,\n',
    'que más cuidados le ofrece;\n',
    'sueña el pobre que padece\n',
    'su miseria y su pobreza;\n',
    'sueña el que a medrar empieza,\n',
    'sueña el que afana y pretende,\n',
    'sueña el que agravia y ofende,\n',
    'y en el mundo, en conclusión,\n',
    'todos sueñan lo que son,\n',
    'aunque ninguno lo entiende.\n']
    
    

    Bytes and Unicode with Files

    不论是读取还是写入,默认的python文件都是 text mode(文本模式),意味着你是与python string(i.e., Unicode)打交道。这和binary mode(二进制模式)形成了对比。这里举个栗子(下面的文件包含non-ASCII字符,用UTF-8编码):

    with open(path) as f:
        chars = f.read(10)
    
    chars
    'Sueña el r'
    

    UTF-8是一种长度可变的Unicode编码,所以我们想要从文件中读取一定数量的字符时,python会读取足够的bytes(可能从10到40)然后解码城我们要求数量的字符。而如果我们用'rb'模式的话,read只会读取相应的bytes数量:

    with open(path, 'rb') as f:
       data = f.read(10)
       
    data
    b'Sue\xc3\xb1a el '
    

    取决于文本的编码,你能够把bytes解码为str,不过如果编码的Unicode字符不完整的话,是无法解码的:

    data.decode('utf8')
    'Sueña el '
    
    data[:4].decode('utf8')
    
    UnicodeDecodeError                        Traceback (most recent call last)
    <ipython-input-21-300e0af10bb7> in <module>()
    ----> 1 data[:4].decode('utf8')
    
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 3: unexpected end of data
    

    在使用open的时候,文本模式是有一个编码选项的,这能更方便我们把一种Unicode编码变为另一种:

    sink_path = '../examples/sink.txt'
    
    with open(path) as source:
        with open(sink_path, 'xt', encoding='iso-8859-1') as sink:
            sink.write(source.read())
    
    with open(sink_path, encoding='iso-8859-1') as f:
        print(f.read(10))
        
    Sueña el r
    

    注意:在任何模式下使用seek打开文件都可以,除了二进制模式。如果文件的指针落在bytes(Unicode编码)的中部,那么之后使用read会报错:

    In [240]: f = open(path)
    
    In [241]: f.read(5)
    Out[241]: 'Sueña'
    
    In [242]: f.seek(4)
    Out[242]: 4
    
    In [243]: f.read(1)
    ---------------------------------------------------------------------------
    UnicodeDecodeError                        Traceback (most recent call last)
    <ipython-input-243-7841103e33f5> in <module>()
    ----> 1 f.read(1)
    /miniconda/envs/book-env/lib/python3.6/codecs.py in decode(self, input, final)
        319         # decode input (taking the buffer into account)
        320         data = self.buffer + input
    --> 321         (result, consumed) = self._buffer_decode(data, self.errors, final
    )
        322         # keep undecoded input until the next call
        323         self.buffer = data[consumed:]
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid s
    tart byte
    
    In [244]: f.close()
    

    我们已经学过了Python的基础、环境和语法,接下来学习NumPy和Python的面向数组计算。
    基本和那个翻译的简书一样,我也不想增加或者删除一些文字了,就稍微加点注释,反正也没人关注,应该不会被说抄袭吧?

    相关文章

      网友评论

          本文标题:【Chapter 3.3】Python 的文件以及操作系统《利用

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