zoukankan      html  css  js  c++  java
  • python文件I/O常用操作

    文件I/O常用操作

    open 打开
    read 读取
    write 写入
    close 关闭
    readline 行读取
    readlines 多行读取
    seek 文件指针操作
    tell 指针位置
    其他

    open打开操作


    打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常

    基本使用:
    创建一个文件test,然后打开它,用完关闭

    f = open("test") #file对象
    # windows <_io.TextIOWrapper name='test' mode='r' encoding='cp935'>
    # linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
    print(f.read()) #读取文件
    f.close() #关闭文件
    
    ---------------------------------------------------------------------------
    
    FileNotFoundError                         Traceback (most recent call last)
    
    <ipython-input-1-f14d31593ce4> in <module>
    ----> 1 f = open("test") #file对象
          2 # windows <_io.TextIOWrapper name='test' mode='r' encoding='cp935'>
          3 # linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
          4 print(f.read()) #读取文件
          5 f.close() #关闭文件
    
    
    FileNotFoundError: [Errno 2] No such file or directory: 'test'
    

    文件操作中,最常用的操作就是读和写。
    文件访问的模式由两种:文本模式和二进制模式。不同模式下,操作函数不尽相同,表现的结果也不一样。# open的参数

    file

    打开或创建的文件名。如果不指定路径,默认时当前路径

    mode模式

    r 缺省的,表示只读打开
    w 只写打开
    x 创建并写入一个新文件
    a 写入打开,如果文件存在,则追加
    b 二进制模式
    t 缺省的,文本模式
    + 读写打开一个文件。给原来只读,只写方式打开提供缺失的读或者写能力
    在上面的例子中,可以看到默认时文本打开模式,且是只读的例子:

    r模式

    ```python #r模式 f = open('test') f.read() f.write('abc') f.close() #默认是只读的,打开文件不可写 ```
    ---------------------------------------------------------------------------
    
    UnsupportedOperation                      Traceback (most recent call last)
    
    <ipython-input-2-6a7832c033e1> in <module>
          2 f = open('test')
          3 f.read()
    ----> 4 f.write('abc')
          5 f.close()
    
    
    UnsupportedOperation: not writable
    

    w模式

    ```python #w模式 f = open('test','w') f.write('好') f.close() f = open('test') f.read() #写模式打开文件,写入数据后关闭(写入方式默认会覆盖原来数据),在使用默认读模式打开,读取文件, ```
    '好'
    

    open默认是只读模式r打开已存在的文件
    r
    只读打开文件,如果使用write方式,会抛出异常
    如果文件不存在,抛出FlieNotFoundError异常
    w
    表示只读方式打开,如果读取则抛出异常
    如果文件不存在,则直接创建文件
    如果文件存在,则清空文件内容

    x模式

    f = open('test2','x')
    f.write('abc')
    f.close()
    f = open('test2')
    f.read()
    
    'abc'
    
    f = open('test2','x')
    
    ---------------------------------------------------------------------------
    
    FileExistsError                           Traceback (most recent call last)
    
    <ipython-input-10-ba6940455994> in <module>
    ----> 1 f = open('test2','x')
    
    
    FileExistsError: [Errno 17] File exists: 'test2'
    

    x
    文件不存在,创建文件,并只写方式打开
    文件存在,抛出FileExistsError异常

    a模式

    f = open('test','a')
    f.write('def')
    f.close()
    f = open('test')
    f.read()
    
    '好def'
    

    文件存在,只写打开,追加内容
    文件不存在,则创建后,只写打开,追加内容

    r是只读,wxa都是只写
    wxa都可以产生新文件,w不管文件存在与否,都会生成全新内容的文件;a不管文件是否存在都能在打开文件尾部追加;x必须要求文件事先不存在,自己造一个新文件

    t模式


    文本模式t
    字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode就是rt。

    b模式


    字节流,讲文件就按照字节理解,与字符编码无关。二进制模式操作时,字节操作使用bytes类型

    f = open('test','rb') #二进制只读
    s = f.read()
    print(type(s)) #bytes
    print(s)
    f.close() #关闭文件
    f = open('test','wb') #IO对象
    s = f.write('啊哈呵'.encode())
    print(s)
    f.close()
    
    <class 'bytes'>
    b'xe5xa5xbddef'
    9
    

    +模式

    ```python # f = open('test','r_') # s = f.read() # f.write('马哥教育1') # print(f.read()) # f.close() # !cat test

    f = open('test','a')
    f.write('123')
    print(f.read())
    f.close()

    
    
        ---------------------------------------------------------------------------
        
        UnsupportedOperation                      Traceback (most recent call last)
        
        <ipython-input-53-72f745833071> in <module>
              8 f = open('test','a')
              9 f.write('123')
        ---> 10 print(f.read())
             11 f.close()
    
    
        UnsupportedOperation: not readable
    
    ### 文件指针
    上面的例子中,已经说明了有一个指针文件指针,指向当前字节位置
    mode = r ,指针起始在0
    mode = a ,指针起始在EOF
    
    [tell() 显示指针当前位置](#tell)
    [seek(offset[,whence])移动文件指针位置](#seek)
    offset偏移多少字节,whence从哪里开发。
    文本模式下
    whence 0 缺省值,表示从头开始,offset只能正整数
    whence 1 表示从当前位置,offset只接受0
    whence 2 表示从EOF位置,offset只接受0
    文本模式支持从开头向后偏移的方式。
    二进制模式下
    whence 0 缺省值,表示从头开始,offset只能正整数
    whence 1 表示从当前位置,offset可正可负
    whence 2 表示从EOF位置,offset可正可负示例:
    <h1 id="tell">tell()</h1>
    ```python
    f = open('test')
    
    f.tell() #默认读模式打开文件,指针在文件起始
    
    0
    
    f.read(1) #读取第一个文字
    
    '马'
    
    f.tell() #指针在第三个字节上,默认为下一个读取的起始位,中文UTF-8编码占三个字节
    
    3
    
    f.read(1) #读取第一个文字
    
    '哥'
    
    f.tell() #中文UTF-8编码占三个字节
    
    6
    
    f.close()
    
    f = open('test','a+') #追加写入
    
    f.tell() #指针默认在文件尾
    
    26
    
    !cat test
    
    马哥1123123123123123123
    
    f.write('你好') #添加
    
    2
    
    f.tell()
    
    32
    
    !cat test #这就是指针,注意尽量不要使用读模式写,指针在文件头部,会覆盖数据
    
    你好1123123123123123123
    
    !echo "马哥1123123123123123123" > test
    
    f = open('test','r+')
    
    f.tell()
    
    0
    
    !cat test 
    
    马哥1123123123123123123
    
    f.write('你好')
    
    2
    
    f.tell()
    
    6
    
    !cat test 
    
    你好1123123123123123123
    

    seek移动文件指针位置

    ```python #文本模式 !echo "abcdefg" > test f = open('test','r+') ```
    f.tell() #起始
    
    0
    
    f.read()
    
    'abcdefg
    '
    
    f.tell() #EOF
    
    8
    
    f.seek(0) #起始
    
    0
    
    f.read()
    
    'abcdefg
    '
    
    f.seek(2,0)
    
    2
    
    f.read()
    
    'cdefg
    '
    
    f.seek(2,0) #offset必须为0
    
    2
    
    f.seek(2,1) #offset必须为0
    
    ---------------------------------------------------------------------------
    
    ValueError                                Traceback (most recent call last)
    
    <ipython-input-227-8e4bcc97d95f> in <module>
    ----> 1 f.seek(2,1) #offset必须为0
    
    
    ValueError: I/O operation on closed file.
    
    f.seek(2,2) #offset必须为0
    
    ---------------------------------------------------------------------------
    
    ValueError                                Traceback (most recent call last)
    
    <ipython-input-226-8025d2a83e5a> in <module>
    ----> 1 f.seek(2,2) #offset必须为0
    
    
    ValueError: I/O operation on closed file.
    
    f.close()
    
    #中文
    f = open('test','w+')
    
    f.write('你好世界')
    
    4
    
    f.tell()
    
    12
    
    !cat test
    
    你好世界
    
    f.close()
    
    f = open('test','r+')
    
    f.read(3)
    
    '你好世'
    
    f.seek(1)
    
    1
    
    f.tell()
    
    1
    
    f.read()
    
    ---------------------------------------------------------------------------
    
    UnicodeDecodeError                        Traceback (most recent call last)
    
    <ipython-input-297-571e9fb02258> in <module>
    ----> 1 f.read()
    
    
    /usr/lib64/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 0xbd in position 0: invalid start byte
    
    f.seek(2)
    
    2
    
    f.read()
    
    ---------------------------------------------------------------------------
    
    UnicodeDecodeError                        Traceback (most recent call last)
    
    <ipython-input-300-571e9fb02258> in <module>
    ----> 1 f.read()
    
    
    /usr/lib64/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 0xa0 in position 0: invalid start byte
    
    f.seek(3)
    
    3
    
    f.read()
    
    '好世界'
    
    f.close()
    

    read读取操作

    read(size=-1) size表示读取的多少个字符或字节;负数或者None表示读取到EOF
    f = open('test','r+',1)
    
    f.write('hello,world')
    
    11
    
    f.write('
    ')
    
    1
    
    f.write('你好世界')
    
    4
    
    f.seek(0)
    
    0
    
    f.read()
    
    'hello,world
    你好世界'
    
    f.close()
    
    #二进制
    f = open('test','rb+')
    
    f.read(7)
    
    b'hello,w'
    
    f.read(1)
    
    b''
    
    f.close()
    

    readline行读取

    readlines多行读取

    readline(size=-1) 一行行读取文件内容。size设置一次能读取行内几个字符或字节 readlines(hint=-1) 读取所有行的列表。指定hint则返回指定的行数
    f = open('test','r+')
    
    f.readline() #一行一行读取,
    为换行符
    
    'hello,world
    '
    
    f.readline() #一行一行读取,
    为换行符
    
    '你好世界'
    
    f.readlines()
    
    ['hello,world
    ', '你好世界']
    

    write写

    write(s),把字符串s写入到文件种并返回字符的个数

    close关闭

    flush并关闭文件对象 文件已关闭,再次关闭没有任何效果

    其他

    seekable() 是否可seek readable() 是否可读 writable() 是否可写 closed 是否已经关闭### 上下文管理1、问题的引出
    lst = [] #列表生成式
    for _ in range(2000): #python range() 函数可创建一个整数列表,一般用在 for 循环中
        lst.append(open('test')) #在列表中执行打开test文件
    
    ---------------------------------------------------------------------------
    
    OSError                                   Traceback (most recent call last)
    
    <ipython-input-387-e2de46ba0013> in <module>
          1 lst = [] #列表生成式
          2 for _ in range(2000): #python range() 函数可创建一个整数列表,一般用在 for 循环中
    ----> 3     lst.append(open('test')) #在列表中执行打开test文件
    
    
    OSError: [Errno 24] Too many open files: 'test'
    
    print(len(lst)) #Python len() 方法返回对象(字符、列表、元组等)长度或项目个数。
    
    959
    

    lsof列出打开的文件。没有就#yum install lsof
    $ lsof -p 1399 | grep test | wc -l

    !lsof -p 959 | grep test | wc -l
    
    0
    

    ulimit -a 查看所有限制。其中open files就是打开文件数的限制,默认1024

    for x in lst:
        x.close()
    

    将文件一次关闭,然后就可以继续打开了。在看一次lsof。如何解决?
    1、异常处理
    当出现异常的时候,拦截异常。但是,应为很多代码都可能出现OSError异常,还不好判断异常就是因为资源限制产生的。

    f = open('test')
    try:
        f.write('abc') #文件只读。写入失败
    finally:
        f.close()#这样才行
        print(f.closed)
    
    True
    
    
    
    ---------------------------------------------------------------------------
    
    UnsupportedOperation                      Traceback (most recent call last)
    
    <ipython-input-8-5115e18cccb3> in <module>
          1 f = open('test')
          2 try:
    ----> 3     f.write('abc') #文件只读。写入失败
          4 finally:
          5     f.close()#这样才行
    
    
    UnsupportedOperation: not writable
    

    使用finally可以保证打开的文件可以被关闭2、python上下文管理一种特殊的语法,交给解释器去释放文件对象

    del f
    with open('test') as f:
        f.write('abc') #文件只读,写入失败
    
    ---------------------------------------------------------------------------
    
    UnsupportedOperation                      Traceback (most recent call last)
    
    <ipython-input-15-db017c97c470> in <module>
          1 del f
          2 with open('test') as f:
    ----> 3     f.write('abc') #文件只读,写入失败
          4 
          5 #测试f是否关闭
    
    
    UnsupportedOperation: not writable
    
    #测试f是否关闭
    f.closed  #f的作用域
    
    True
    

    1、使用with ... as 关键字
    2、上下文管理的语句块并不会开启新的作用域
    3、with语句执行完的时候,会自动关闭文件对象另一种写法

    f1 = open('test')
    with f1:
        f1.write('abc') #文件只读,写入失败
    
    ---------------------------------------------------------------------------
    
    UnsupportedOperation                      Traceback (most recent call last)
    
    <ipython-input-17-3ef7ddf3fe9b> in <module>
          1 f1 = open('test')
          2 with f1:
    ----> 3     f1.write('abc') #文件只读,写入失败
    
    
    UnsupportedOperation: not writable
    
    f1.closed
    
    True
    

    对于类似于文件对象的IO对象,一般来说都需要在不使用的时候关闭,注销,以释放资源。
    IO被打开的时候,会获得一个文件描述符。计算机资源是有限的,所以操作系统都会做限制。就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,不是独占的。
    一般情况下,除非特别明确的知道资源情况,否则不要提高资源的限制值来解决问题。

    路径操作

    3.4版本开始
    建议使用pathlib模块,提供Path对象来操作,包括目录和文件。
    pathlib模块
    获取路径
    父路径
    通配符
    匹配
    文件操作

    pathlib模块

    # pathlib模块
    from pathlib import Path
    #目录操作
    #初始化
    p = Path()#不加参数为当前路径
    print(p)
    p = Path('a','b','c/d') #当前路径下的a/b/c/d
    print(p)
    p = Path('/etc') #根下的etc目录
    print(p)
    
    .
    a/b/c/d
    /etc
    

    路径拼接和分解
    操作符/
    Path对象/Path对象
    Path对象/字符串 或者 字符串/Path对象
    分解
    parts属性,可以返回路径中的每一个部分
    joinpath
    joinpath(*other)连接多个字符串到Path对象中

    p = Path()
    p = p / 'a'
    print(p)
    p1 = 'b' / p
    print(p1)
    p2 = Path('c')
    p3 = p2 / p1
    print(p3.parts)
    p3.joinpath('etc','init.d','Path(httpd)')
    
    a
    b/a
    ('c', 'b', 'a')
    ('c', 'b', 'a')
    
    
    
    
    
    PosixPath('c/b/a/etc/init.d/Path(httpd)')
    

    获取路径

    str获取路径字符串 bytes获取路径字符串的bytes
    p = Path('/etc')
    print(str(p),bytes(p))
    
    /etc b'/etc'
    

    父目录

    parent目录的逻辑父目录 parents父目录序列,索引0是直接的父
    p = Path('a/b/c/d')
    print(p.parent.parent.parent)
    print(p.parent.parent)
    for x in p.parents:
        print(x)
    
    a
    a/b
    a/b/c
    a/b
    a
    .
    

    name,stem,suffix,suffixes,with_suffix(suffix),with_name(name)
    name 目录的最后一个部分
    suffix 目录中最后一个部分的扩展名
    stem 目录最后一个部分,没有后缀
    suffixes 返回多个扩展名列表
    with_suffix(suffix) 补充扩展名到路径的尾部,返回新的路径,扩展名存在则无效
    with_name(name)替换目录最后一个部分并返回一个新的路径

    p = Path('/etc/sysconfig/network-scripts/ifcfg.enp0s3')
    print(p.stem)
    print(p.name)
    p1 = Path(str(p) + '.gz')
    print(p1)
    print(p1.suffix)
    print(p1.suffixes)
    print(p1.with_suffix('.zig'))
    print(p1.with_name('nihao'))
    # 另一种方法
    print(p1.parent / 'test') #拼接
    
    ifcfg
    ifcfg.enp0s3
    /etc/sysconfig/network-scripts/ifcfg.enp0s3.gz
    .gz
    ['.enp0s3', '.gz']
    /etc/sysconfig/network-scripts/ifcfg.enp0s3.zig
    /etc/sysconfig/network-scripts/nihao
    /etc/sysconfig/network-scripts/test
    

    cwd() 返回当前系统工作路径
    home() 返回当前家目录

    print(p)
    print(p.cwd())
    print(p.home())
    
    /etc/sysconfig/network-scripts/ifcfg.enp0s3
    /root
    /root
    

    is_dir() 是否是目录
    is_file() 是否是普通文件
    is_symlink() 是否是软链接
    is_socket() 是否是socket文件
    is_block_device 是否是块设备
    is_char_device() 是否是字符设备
    is_absolute() 是否是绝对路径resolve() 返回一个新路径,这个新路径就是当前Path对象的绝对路径,如果是软链接则直接被解析
    absolute() 也可以获取据对路径,但是推荐使用resolve()exists() 目录或文件是否存在
    rmdir() 删除空目录。没有提供判断目录为空的方法
    touch(mode=0o666,exist_ok=True)创建一个文件
    as_uri()将路径返回成URI,例如"file:///etc/passwd"mkdir(mode=0o777,parents=False,exist_ok=False)
    parents,是否创建父目录,True等同于mkdir -p; False时,父目录不存在,则抛出FileNotFoundError
    exist_ok参数,在3.5版本加入。False时,路径存在,抛出FileNotFoundError;True时,FileNotFoundError被忽略
    iterdir() 迭代当前目录

    from pathlib import Path
    p = Path()
    print(p)
    print(p.cwd())
    p /= 'a/b/c/d'
    print(p)
    p.exists() #True
    
    .
    /root
    a/b/c/d
    
    
    
    
    
    False
    
    #创建目录
    # p.mkdir() #直接创建会抛出异常FileNotFoundError
    # print(p) #没有父目录
    p.mkdir(parents=True) #
    p.exists() #True
    # p.mkdir(parents=True)
    # p.mkdir(parents=True,exist_ok=True)
    # p /= 'readme.txt'
    # p.parent.rmdir()
    # p.parent.exists() #False '/a/b/c'
    # p.mkdir() #FileNotFoundError
    
    True
    
    #遍历,并判断文件类型,如果是目录是否可以判断其是否为空
    for x in p.parents[len(p.parents)-1].iterdir():
        print(x,end='/t')
        if x.is_dir():
            flag = False
            for _ in x.iterdir():
                flag = True
                break
            #for 循环是否可以使用else子句
            print('dir','Not Empty' if flag else 'Empyt',sep='/t')
        elif x.is_file():
            print('file')
        else:
            print('other file')
    
    .bash_logout/tfile
    .bash_profile/tfile
    .bashrc/tfile
    .cshrc/tfile
    .tcshrc/tfile
    anaconda-ks.cfg/tfile
    .lesshst/tfile
    .viminfo/tfile
    .cache/tdir/tNot Empty
    .bash_history/tfile
    .python_history/tfile
    .local/tdir/tNot Empty
    未命名.ipynb/tfile
    .ipynb_checkpoints/tdir/tNot Empty
    .ipython/tdir/tNot Empty
    未命名1.ipynb/tfile
    test2/tfile
    test/tfile
    .jupyter/tdir/tNot Empty
    a/tdir/tNot Empty
    

    通配符

    glob(pattern)通配给定的模式 rglob(pattern)通配给定的模式,递归目录 返回一个生成器
    p = Path('/root')
    print(p)
    # list(p.golb('test*')) #返回当前目录对象下的test开头的文件
    list(p.glob('**/*.py')) #递归所有目录,等同rglob
    
    /root
    
    
    
    
    
    [PosixPath('/root/1.py'), PosixPath('/root/a/2.py')]
    
    g = p.rglob('*.py')
    next(g)
    
    PosixPath('1.py')
    

    匹配

    match(pattern) 模式匹配,成功返回True
    Path('a/b.py').match('*.py') #True
    Path('a/b/c.py').match('b/*.py') #False
    Path('a/b/c.py').match('a/*.py') #True
    Path('a/b/c.py').match('a/*/*.py') #True
    Path('a/b/c.py').match('a/**/*.py') #True
    Path('a/b/c.py').match('**/*.py') #True
    

    stat()相当与stat命令
    lstat()同stat(),但如果是符号链接,则显示符号链接本身的文件信息

    !ln -s test t
    from pathlib import Path
    p = Path('test')
    p.stat()
    p1 = Path('t')
    p1.stat()
    p1.lstst()
    

    文件操作

    open(mode='r',buffering=-1,encoding=None,errors=None,newline=None) 使用方法类似内建函数open。返回一个文件对象3.5增加的新函数 read_bytes() 以'rb'读取路径对应的文件,并返回二进制流。看源码read_text(encoding= None,errors=None) 以'rt'方式读取路径对应的文件,返回文本。 Path.write_bytes(data) 以'wb'方式写入数据到路径对应的文件 write_text(data,encoding=None,errors=None) 以'wt'方式写入字符串到路径对应的文件
    p = Path('my_binary_file')
    p.write_bytes(b'Binary file contents')
    p.read_bytes() #b'Binary file contents'
    
    p = Path('my_text_file')
    p.write_text('Text file contents')
    p.read_text() #'Text file contents'
    
    from pathlib import Path
    p = Path('o:/test.py')
    p.write_text('hello python')
    print(p.read_text())
    with p.open() as f:
        print(f.read(5))
    
  • 相关阅读:
    推荐一本不错的书《Sencha Ext JS 5 Bootcamp in a Book》
    Libgdx 1.6.0发布,跨平台游戏开发框架
    《.NET最佳实践》与Ext JS/Touch的团队开发
    【翻译】Sencha Cmd中脚本压缩方法之比较
    【翻译】Ext JS 6早期访问版本发布
    【翻译】Ext JS 6有什么新东西?
    SpringBoot 使用 MyBatis 分页插件 PageHelper 进行分页查询
    Spring boot+Thymeleaf+easyui集成:js创建组件页面报错
    SpringBoot多模块搭建,依赖管理
    IDEA在同一窗口导入多个项目
  • 原文地址:https://www.cnblogs.com/hao-ran/p/11708478.html
Copyright © 2011-2022 走看看