五.Python文件IO和路径操作

目录

  • Python文件IO操作
  • 上下文管理with
  • 路径操作

01 Python文件IO操作:

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

打开文件

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
示例

f = open('test')
# windows < io.TextIOWrapper name='test', mode='r', encoding='cp936'
# linux < io.TextIOWrapper name='test', mode='r', encoding='utf-8'
print(f.read())
f.close()

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

open的参数

  • file 打开或者要创建的文件名,如果不指定路径,默认是当前路径
    文件描述符
    0 1 2已经被占用

  • mode模式
    r 缺省的,表示只读打开
    w 只写打开
    x 创建并写入一个新文件
    a 写入打开,如果文件存在,则追加
    b 二进制模式打开
    t 缺省的,文本模式
    + 读写打开一个文件,给原来只读、只写方式打开提供缺失的读或者写能力

模式 描述
r 模式 只读打开文件,如果使用write方法,则会抛出异常;如果文件不存在,抛出FileNotFoundError异常
w 只写打开,如果读取则抛出异常;如果文件不存在,则直接创建文件;如果文件存在,则清空文件内容
x 文件不存在,创建文件,并只写方式打开;文件存在,抛出FileExistsError异常
a 文件存在,只写打开,追加内容;文件不存在,则创建后,只写打开,追加内容
r只读,wxa都是只写 wxa都可以产生文件,w不管文件存在与否,都会生成全新内容的文件;a不管文件是否存在,都能在打开的文件尾部追加;x必须要求文件事先不存在,自己造一个文件。
文本模式t 字符流,将文件的字节按照某种字符编码理解,按照字符操作。默认模式。
二进制模式b 字节流,将文件按照字节理解,与字符编码无关。二进制模式操作时,字节操作使用bytes类型。
  • 文件指针
    mode = r 指针起始在0
    mode = a 指针起始在EOF(文件末尾)
  • tell() 显示指针位置
  • seek(offset[,whence]) 移动指针. offset偏移多少字节。
    文本模式下:
    whence 0 缺省值,表示从头开始,只接受正整数
    whence 1 表示从当前位置 ,只接受0
    whence 2表示从EOF位置开始,只接受0
    字节模式:
    wence 0 缺省值,表示从头开始,offset只接受正整数
    whence 1 表示从当前位置 ,offset可正可负
    whence 2表示从EOF位置开始,offset可正可负

    常用函数

    函数 说明
    read(size=-1) 默认读取所有,文本模式下为读取字符数量,字节模式下为字节数
    readline(size=-1) 一次读取多少行内容,默认所有
    readlines 读取多行内容
    write(s) 把字符串s写入到文件中,并返回字符的个数
    close() flush并关闭文件对象,关闭后,再次关闭没有效果

其他函数

函数 说明
seekable() 是否可seek
readable() 是否可读
writeabel() 是否可写
closed() 是否已经关闭

02 上下文管理

引出:

#
lst = []
for _ in range(2000):
    lst.append(open("test"))
# OSError: [Errno 24] Too many open files:'test'
print(len(lst))

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

解决办法:

1.异常处理
当出现异常的时候,拦截异常,但是很多代码都可能出现OSError异常,还不好判断异常就是因为资源限制产生的。

f = open('test')
try:
    f.write('abc')
finally:
    f.close()

使用finally 可以保证所有文件可以被关闭。

2.上下文管理
一种特殊的语法,交给解释器去释放文件。

with open('test') as f:
    f.read()

使用with...as关键字:
上下文管理语句并不会开启新的作用域
with语句块执行完的时候,会自动关闭文件对象

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

StingIO和BytesIO

  • StingIO
    io模块中类: from io import StringIO
    内存中,开辟的一个文本模式的buffer,可以像文件对象一样操作它
    当close方法被调用的时候,这个buffer会被释放
    getvalue() 获取全部内容,跟文件指针没有关系
from io import StingIO
sio = StringIO() # 跟文件操作类似
sio.write("test context")
sio.seek(0)
print(sio.getvalue())
print(sio.readline())
sio.close()
  • BytesIO
    io模块中类: from io import BytesIO
    内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它
    当close方法被调用的时候,这个buffer会被释放
    getvalue() 获取全部内容,跟文件指针没有关系

与StringIO相似。
好处:一般来说,磁盘操作比内存操作慢的多,内存足够的情况下,一般的优化是少落地,减少磁盘IO的过程,可大大提高程序的运行效率。

  • file-like对象
    类文件对象,可以像文件对象一样操作
    socke对象、输入输出对象(stdin、stdout)都是类文件对象
from sys import stdout
f = stdout
print(type(f))
f.write('leafgood.com')

03 路径操作

路径操作模块

  • 3.4版本之前:os.path模块
from os import path
p = path.join('/etc'. 'sysconfig', 'network')
print(type(p), p)
print(path.exists(p))
print(path.split(p))
print(path.abspath('.'))
p = path.join('o:/', p, 'text.txt')
print(path.dirname(p))
print(path.basename(p))
print(path.splitdrive(p)) # window下使用
  • 3.4版本之后:pathlib模块,提供path对象来操作,包括目录和文件。
from pathlib import Path
p = Path()
p.absolute() #绝对路径
p = p.joinpath('a','b')
p.absolute()
p = p / 'c'  #拼接 等价于 p / = 'c' , p = p.joinpath('c')
#目录初始化
p = Path() #当前目录
p = Path('a', 'b', 'c/d') #当前目录下a/b/c/d
p = Path('/etc')

路径拼接和分解

操作符 /
Paht对象 / Path对象
Path对象 / 字符串 或者 字符串/Path对象

分解
parts属性,可以返回路径中的每一个部分

joinpath
joinpath(*others) 连接多个字符串到Path对象

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

父目录
p.parent
p.parents 返回一个可迭代对象
示例

>>> p.parents
<PosixPath.parents>
>>> list(p.parents)
[PosixPath('/home/zhaow/py/c/d'), PosixPath('/home/zhaow/py/c'), PosixPath('/home/zhaow/py'), PosixPath('/home/zhaow'), PosixPath('/home'), PosixPath('/')]
>>> p.parent
PosixPath('/home/zhaow/py/c/d')
>>> p.parent.parent
PosixPath('/home/zhaow/py/c')

相对路径转化成绝对路径后,再获取父目录,parent可以连续
name 目录的最后一个部分
suffix 目录最后一个部分的扩展名.后缀
stem 目录最后一个部分,没有后缀名
suffixes 返回多个扩展名列表
with_suffix(suffix) 补充扩展名到路径,或者替换扩展名
with_name(name) 替换目录最后一个部分并返回一个新的路径

>>> p
PosixPath('/home/zhaow/py/c/d/c/d.ifg.zip')
>>> p.name
'd.ifg.zip'
>>> p.stem
'd.ifg'
>>> p.suffix
'.zip'
>>> p.suffixes
['.ifg', '.zip']
>>> p.with_suffix('.gz')
PosixPath('/home/zhaow/py/c/d/c/d.ifg.gz')
>>> p.with_name('gz')
PosixPath('/home/zhaow/py/c/d/c/gz')
>>> p
PosixPath('/home/zhaow/py/c/d/c/d.ifg.zip')

不修改原路径:
cwd() 返回当前工作目录
home() 返回当前家目录

is_dir()是否是目录
is_file() 是否是文件
is_symlink()是否是软链接
is_socket() 是否是socket文件
is_block_device() 是否是块设备文件
is_char_device() 是否是字符设备
is_absolute() 是否是绝对路径

resolve() 返回一个新的路径,这个新路径就是当前Path对象的绝对路径,如果是软链接直接解析
absolute()
exists() 目录或者文件是否文件
rmdir() 删除空目录,没有提供判断目录为空的方法
touch(mode=0o666, exist_ok=True) 创建一个新文件
as_uri() 将路径返回成url

mkdir(mode=0o777, parents=False, exist_ok=False)
-- parents 是否创建父目录,True等同于mkdir -p

iterdir()迭代当前目录内容,返回一生成器对象

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
        print('dir', 'Not Empty' if flag else 'Empty', sep='\t')
    elif x.is_file():
        print('file')
    else:
        print('other file')

通配符:
glob(pattern) 通配给定的模式

>>> list(p.glob('*/m*'))  #一个* 任意字符下
[PosixPath('Aclsm/manage.py')]
>>> list(p.glob('*m*'))
>>> list(p.glob('**/m*')) #任意字符任意级别

rglob(pattern) 通配给定的模式,递归目录

匹配
match(pattern) 模式匹配成功,返回True

>>> Path('a/b.py').match('*.py')
True
>>> Path('a/b/c.py').match('*.py')
True
>>> Path('a/b/c.py').match('b/*.py')
True
>>> Path('a/b/c.py').match('a/*.py')
False
>>> Path('a/b/c.py').match('a/**/.py')
False
>>> Path('a/b/c.py').match('a/**/*.py')
True
>>> Path('a/b/c.py').match('**/*.py')
True

文件操作
p = Path()
p.open(mode='r,buffering=-1,encoding=None,errors=None,newline=None)
使用方法类似内建函数open,返回一个文件对象
可以使用with语句

with p.open('w') as f:
    pass

3.5增加的新函数
p.write_text(content) #每次打开会清空,重新数据
p.write_bytes(content) #每次打开会清空,重写数据
p.read_text()
p.read_bytes()

猜你喜欢

转载自www.cnblogs.com/luckyleaf/p/12112792.html
今日推荐