Python3 IO编程
Contents
Python IO编程值得是经常涉及到文件处理和操作得各种方法得应用,本文是学习笔记,主要参考廖雪峰《Python3教程》和部分网络学习资源。
IO
在计算机中指 Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由 CPU 这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要 IO 接口。
IO 编程简单理解指的是你的程序涉及到 cpu、内存和磁盘、网络的数据交互。因为 cpu、内存和磁盘、网络的速度有差异,所以在 IO 编程中,就存在速度严重不匹配的问题,比如网络爬虫的实例,网页解析可能只要 0.001秒,但是下载网页可能要 0.1s,为解决速度不匹配的问题,可以使用异步 IO,使用异步 IO 来编写程序性能会远远高于同步 IO,但是异步 IO的缺点是编程模型复杂。
操作 IO 的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级 C 接口封装起来方便使用, Python 也不例外。
文件读写
文件读写是最常见的 IO 操作。 Python 内置了读写文件的函数,用法和C 是兼容的。读写文件前,我们清楚,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。(来源,《Python3教程》-廖雪峰)
读文件
(来源见这里)
Python 读取文件的一般“标准做法“是,首先使用 with open(fine_name)
上下文管理器的方式打开一个文件并获得文件对象,然后使用 for
循环迭代它,逐行获取文件里的内容,如果该文件无法被打开,会抛出 OSError
。用法示例如下:
try:
with open(demo.txt, 'r') as f:
lines = f.readlines()
for idx ,line in enumerate(lines):
print(line) # 循环打印demo.txt的每一行内容
except Exception as e:
print(e)
print(traceback.print_exc())
file
对象使用 open
函数创建,file 对象的常用函数如下:
file.readline()
可以每次读取一行内容,包括 “\n” 字符(f
指的是文件对象)。file.readlines()
一次读取所有内容并按行返回list
,行字符串末尾也包含了换行符 “\n”,可用 strip(“\n”) 方法去除。file.read(chunk_size)
返回从当前位置往后读取chunk_size
大小的文件内容 。file.read()
可以一次读取文件的全部内容到内存中,用一个str
对象表示。
调用 read()
会一次性读取文件的全部内容,如果文件有 10G,内存就爆了,所以,要保险起见,可以反复调用 read(size)
方法,每次最多读取 size
个字节的内容。另外,调用 readline()
可以每次读取一行内容,调用 readlines()
一次读取所有内容并按行返回 list
,因此,要根据需要决定怎么调用。
如果文件很小, read() 一次性读取最方便;如果不能确定文件大小,反复调用 read(size) 比较保险;如果是配置文件,调用 readlines()最方便。
file-like Object
像 open() 函数返回的这种有个 read() 方法的对象,在 Python 中统称为 file-like Object
。除了 file 外,还可以是内存的字节流,网络流,自定义流等等。file-like Object 不要求从特定类继承,只要写个 read() 方法就行。
写文件
写文件和读文件是一样的,也用open()函数,唯一区别是调用 open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件。
代码示例如下:
with open(txt_fpath, 'w') as f:
# start write str sequence
f2.writelines(line2s)
f.write(str)
:将字符串写入文件,返回的是写入的字符长度。f.writelines(sequence)
:向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。
总结
open()
函数完整的语法格式如下:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
在 Python 中,文件的读写都是通过 open()
方法实现的,区别在于 mode
参数不同。在 Python 中,文件的读写都是通过 open()
方法实现的,区别在于 mode
参数不同;使用 open() 方法一定要保证关闭文件对象,即调用 close()
方法。
操作文件和目录
在 Python 中,操作文件和目录的函数一部分放在 os
模块中,一部分放在 os.path
中。os
模块是操作系统接口模块,该模块提供了一些方便使用操作系统相关功能的函数。 如果想读写一个文件,请参阅 open() 函数,如果你想操作路径,请参阅 os.path
模块,如果你想在命令行上读取所有文件中的所有行请参阅 fileinput
模块。 有关创建临时文件和目录的方法,请参阅 tempfile
模块,对于高级文件目录处理,请参阅 shutil
模块。
os.path 模块常用函数
os.path
模块主要用于获取文件的属性,os.path
模块的函数都仅接受(Unicode)字节或字符串对象(路径)作为其参数。如果返回路径或文件名,则结果是相同类型的对象。os.path 模块的几种常用函数如下,这些函数的灵活应用需要自己在涉及操作文件/目录中的实例中灵活应用和总结。
os.getcwd()
返回当前工作目录os.path.realpath(path)
返回 path 的真实路径os.path.abspath(path)
返回 path 的绝对路径os.path.abspath(os.path.join(os.getcwd(), ".."))
返回当前目录的上一级目录的绝对路径os.path.abspath(os.path.join(os.getcwd(), "../../"))
返回当前目录的上上级目录的绝对路径
os.path.basename(path)
返回文件名os.path.splitext(filename)
返回文件路径和文件后缀分割后的字符串元组
实例代码如下:
import os
print(os.getcwd().replace('\\\\', '/'))
print(os.listdir('./')) # 列出当前目录下的所有子目录和文件名
os.path.abspath('./opencv_demo.py')
print(os.path.realpath('./').replace('\\', '/'))
print(os.path.abspath('../').replace('\\', '/'))
# 当path存在软链接时,两者有所区别,其他时候无区别
# os.path.realpath 会返回指定文件的标准路径,而非软链接所在的路径
程序输出如下:
C:/Users/zhanghonggao/Documents/image_utils/tools [‘.ipynb_checkpoints’, ‘crawl_images.py’, ‘daily_experiment.py’, ‘demo-image-classification-fastai’, ‘image_process.ipynb’, ‘input_nums.py’, ‘opencv_demo.py’, ‘pyqt5_demo.py’, ‘python3_practice.py’] C:/Users/zhanghonggao/Documents/image_utils/tools C:/Users/zhanghonggao/Documents/image_utils
os.path.exists() 和 os.path.isdir()、os.path.isfile() 等函数
os.path.exists(path)
方法可以直接判断文件/文件夹
是否存在,功能相当于 os.path.isdir()、os.path.isfile() 的集合。os.path.isfile(path)
判断指定对象是否为文件。是返回 True,否则 False。os.path.isdir(path)
判断指定对象是否为目录(文件夹)。是返回 True,否则 False。os.path.islink(path)
判断路径是否为链接
os.path.basename 和 os.path.dirname 函数
os.path.basename(path)
去掉目录路径,返回文件名os.path.dirname(path)
去掉文件名,返回目录路径
os.path.split() 和 os.path.splitext() 函数
os.path.split(path)
返回( dirname(), basename())元组,basename是文件名(basename)os.path.splitext(path)
返回 (filename, extension) 元组,extension是文件后缀
os.path.getmtime() 和 os.path.getctime() 函数
os.path.getmtime(path)
返回最近文件修改时间os.path.getctime(path)
返回 path 创建时间(windows系统),返回值是一个数,为纪元秒数(参考 time 模块)。如果该文件不存在或不可访问,则抛出 OSError 异常。
os.mkdir 和 os.makedirs 函数
path = '/test/path_01/path_02/path03/'
os.mkdir
函数只会创建path
路径的最后一级目录os.makedirs
函数递归地创建多层目录,如果 path 的四级目录都没有,则会自动递归创建全部 test、path_01、path_02、path_03 这 4 个目录
os.walk() 和 os.path.getsize() 函数
os.path.getsize(path)
返回文件大小,如果文件不存在就返回错误os.walk(top, topdown=True, onerror=None, followlinks=False)
创建一个生成器,用以生成所要查找的目录及其子目录下的所有文件。
os.walk
函数可以得到一个三元tupple(dirpath, dirnames, filenames) generator
,可 for
循环遍历这个 generaor
,得到所有目录(包括子目录)的三元 tuple
。tuple
第一个元素为起始路径,第二个为起始路径下的文件夹,第三个是起始路径下的文件。
dirpath
是一个 string,代表目录的路径。(文件夹路径)dirnames
是一个 list,包含了 dirpath 下所有子目录的名字。(文件夹名字)filenames
是一个 list,包含了非目录文件的名字。(文件名)
os.walk(root_dir)
先遍历 root_dir 目录下的第一个子目录,再依次遍历第二、第三、第 n 个目录,每遍历一个子目录都得到一个 generator
。实例代码: python 获取文件夹大小。
"""python 获取指定文件夹大小"""
import os
f_dir = os.path.abspath(os.path.dirname(__file__))
def get_dir_size(dir):
size = 0
for root, dirs, files in os.walk(dir):
size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
return size
if __name__ == '__main__':
size = get_dir_size('../')
print('Total size is: %.3f Mb'%(size/1024/1024))
序列化
我们把变量从内存中变成可存储或传输的过程称之为序列化,在 Python中叫 pickling,在其他语言中也被称之为 serialization, marshalling,flattening 等等,都是一个意思。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即 unpickling。 Python中提供了pickle模块实现对象的序列化,常用方法如下:
pickle.dumps()
方法把任意对象序列化成一个 bytes,然后,就可以把这个 bytes 写入文件pickle.dump()
方法直接把对象序列化后写入一个 file-like Objectpickle.loads()
方法用于从bytes中反序列化出对象pickle.load()
方法从一个 file-like Object 中直接反序列化出对象,
**这些方法的应用,建议到实际工程代码中去练习,才能理解和灵活应用**。实例代码如下:
import pickle
d = dict(name='Bob', age=20, score=88)
with open('demo.txt', 'wb') as f:
pickle.dump(d, f)
with open('demo.txt', 'rb') as f:
d = pickle.load(f)
print(d)
程序输出如下:
{‘name’: ‘Bob’, ‘age’: 20, ‘score’: 88}
Json
json.loads()、 json.dumps()
函数适用于json格式的字符串对象json.load()、json.dump()
函数适用于json文件,
dumps()方法返回一个 str,内容就是标准的 JSON。类似的, dump()方法可以直接把 JSON 写入一个 file-like Object。 要把 JSON 反序列化为 Python 对象,用 loads()或者对应的 load()方法,前者把 JSON 的字符串反序列化,后者从 file-like Object 中读取字符串并反序列化
JSON 表示的对象就是标准的 JavaScript 语言的对象, JSON 和 Python内置的数据类型对应如下:
总结
Python官方的对象序列化模块是pickle,实际工程中发现使用pickle文件反序列化出对象速度更快,但如果要把序列化搞得更通用、更符合 Web 标准,建议使用 json 模块。
参考资料
《Python教程-廖雪峰》 Python 工匠:高效操作文件的三个建议
相关文章
- pycharm安装dlib失败_python3.8.0安装教程
- python3.7安装pip_centos怎么安装
- pycharm安装python3.6_python安装教程
- python3.7如何安装numpy库_python升级后第三方库
- win10系统下pycharm2017配置opencv-python3.4.5[通俗易懂]
- dockerfile制作:制作python3下的robotframework运行环境
- centos安装python3详细教程[通俗易懂]
- python3 三种字符串(无前缀,前缀u,前缀b)与encode()「建议收藏」
- 翻身了?Python3.11性能测评超3.10近64%
- pycharm中tensorflow配置环境_python3.6安装tensorflow
- 失控的 Python3 类型
- python3生成随机数_用python随机输出一个区间的随机数
- 关于Python3的import问题(pycharm可以运行,命令行import错误)
- python3中pygame安装过程(超级详细)
- 树莓派4B安装Tensorflow(Python3.5和3.7下分别进行安装)
- qpython3安装pygame_详解Python pygame安装过程笔记
- 大整数乘法python3实现
- [Python3]pandas.merge用法详解
- 无法安装python3的连续报错-mysql include软链接问题
- python3 高斯函数