Learn Python 3:IO操作

一、读文件

1、读取整个文件

准备好一个非空的txt文件

# 通过绝对路径读取文件
>>> with open(r'C:\Users\dell\Desktop\io\zen.txt') as f:
...     print(f.read())
... 
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
>>>
# 通过相对路径读取文件
>>> with open(r'io\zen.txt') as f:
...     print(f.read())
...
# 通过文件名读取
>>> with open('zen.txt') as f:
...     print(f.read())
...

LinuxMac OS中,文件路径中使用斜杠(/),在Windows中,文件路径中使用反斜杠(\),但是为了防止反斜杠和后边跟的字母发生转义,建议在路径前加 r 符号或者使用双反斜杠(\\

使用绝对路径读取文件,Python将在指定的绝对路径查找文件。

使用相对路径读取文件,Python将在当前执行的文件
(即.py程序文件)所在目录的子目录中查找文件。

使用文件名读取文件,Python将在当前执行的文件
(即.py程序文件)所在目录中查找文件。

使用with语句打开文件,在文件不需要访问后会自动将其关闭。

由于read()方法会一次读取文件全部内容,如果文件太大,可能导致内存不够用,为此可以使用read(size)方法,每次最多读取size个字节的内容。

2、逐行读取
>>> with open('zen.txt') as f:
...     for line in f:
...         print(line)
...
Beautiful is better than ugly.

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

因为在这个文件中,每行的末尾都有一个看不见的换行符,而print语句也会加上一个换行符,因此每行末尾都有两个换行符,可以通过rstrip()方法去掉多余换行符。

print(line.rstrip())

每次读取一行文件:

>>> with open('zen.txt') as f:
...     print(f.readline().rstrip())
...     print(f.readline().rstrip())
...
Beautiful is better than ugly.
Explicit is better than implicit.

读取所有行:

>>> with open('zen.txt') as f:
...     for line in f.readlines():
...         print(line.rstrip())

readlines()方法会一次读取所有文件内容并按行返回一个list

3、字符编码

如果要读取指定编码格式的文件,给open()方法设置encoding参数,例如读取GBK编码的文件:

>>> with open('test.txt', 'r', encoding='GBK') as f:
...     print(f.read())
...
中国

如果在文本有一些非法编码的字符,可能出现UnicodeDecodeError错误,可给open()方法再设置一个errors参数,表示遇到错误后如何处理,常见参数值有如下几个可选:

  • ignore:忽略错误
  • strict:编码出错则抛出异常ValueError
  • replace:使用指定字符替代出错的字符
4、读取二进制文件

除了文本文件,还可以读取二进制文件,比如图片:

>>> with open(r'io\launcher.png', 'rb') as f:
...     print(f.read())
...
b'\x89PNG\r\n\x1a\n\x00\x00\x00......'

注意指定rb 打开模式

二、写文件

>>> with open(r'io\test.txt', 'w') as f:
...     print(f.write('Hello World'))
...
11

可以看到通过write()来写入文本,并返回了文本长度。这样在test.txt文件中写入了字符串Hello World

  • 如果要指定写入文本的编码格式,可给open()函数设置encoding参数,将文本自动转换成指定编码。

  • 打开文件时,可指定读取模式:r、 写入模式:w、 附加模式:a(如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件)、或能够读取和写入文件的模式:r+:。如果你省略了模式Python将以默认的只读模式打开文件。

  • 如果要写入的文件不存在,函数open()将自动创建它。如果以写入(w)模式打开文件时需要注意,若指定的文件已经存在, Python将在返回文件对象前清空该文件。

  • Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式。

三、StringIO

StringIO可以是在内存中读写str

通过write()方法写入str,通过getvalue()获得写入的str

>>> from io import StringIO
>>> si = StringIO()
>>> si.write('Hello World')
11
>>> print(si.getvalue())
Hello World
>>> 

直接使用str初始化一个StringIO,类似读文件一样获得写入的str:

>>> from io import StringIO
>>> si = StringIO('Hello World')
>>> print(si.readline())
Hello World
>>>

四、BytesIO

BytesIO可以在内存中读写二进制数据(bytes

用法和StringIO类似:

>>> from io import BytesIO
>>> bi = BytesIO()
>>> bi.write('中国'.encode('utf-8'))
6
>>> print(bi.getvalue())
b'\xe4\xb8\xad\xe5\x9b\xbd'
>>>
>>> from io import BytesIO
>>> bi = BytesIO(b'\xe4\xb8\xad\xe5\x9b\xbd')
>>> bi.read()
b'\xe4\xb8\xad\xe5\x9b\xbd'
>>>

五、文件和目录操作

先导入osshutil模块:

import os, shutil
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'C:\\Users\dell\\Desktop\\learn'
# 当前Python脚本工作的目录路径
>>> os.getcwd()
'C:\\Users\dell\\Desktop\\learn'
# 路径拼接
>>> os.path.join('learn', 'testdir')
'learn\\testdir'
# 路径拆分
>>> os.path.split(r'learn\a.txt')
('learn', 'a.txt')
# 获取文件后缀名
>>> os.path.splitext(r'learn\a.txt')
('learn\\a', '.txt')
# 创建一个目录:
>>> os.mkdir('testdir')
# 删除一个目录:
>>> os.rmdir('testdir')
# 重命名文件(a.txt ——> b.txt)
>>> os.rename('a.txt', 'b.txt')
# 删除文件:
>>> os.remove('b.txt')
# 返回指定目录下的所有文件和目录名,点号代表当前目录
>>> os.listdir('.')
['a.txt', 'launcher.png', 'testdir', 'zen.txt']
# 判断是否是文件
>>> os.path.isfile('a.txt')
True
# 判断是否是目录
>>> os.path.isdir('testdir')
True
# 获取文件大小
>>> os.path.getsize('launcher.png')
7718
# 判断是否是绝对路径
>>> os.path.isabs('testdir')
False
# 判断路径是否存在
>>> os.path.exists('testdir')
True
# 获取文件名
>>> os.path.basename(r'testdir\b.txt')
'b.txt'
# 复制文件,复制a.txt
>>> shutil.copyfile('a.txt', 'a2.txt')
'a2.txt'
# 将文件复制到文件夹,复制a.txt到testdir目录
>>> shutil.copy('a.txt', 'testdir')
'testdir\\a.txt'
# 复制文件夹,复制testdir文件夹,新文件夹名为test
>>> shutil.copytree('testdir', 'test')
# 移动原文件夹到目标文件夹,如果目标文件夹不存在则相当于重命名原文件夹
>>> shutil.move('testdir', 'test')
'test\\testdir'

六、序列化

1、pickle

Python中提供了 pickle模块来实现序列化。
首先导入pickle模块:

>>> import pickle
  • 将一个Python对象序列化:
>>> d = {'name': 'tom', 'age': 18}
>>> bs = pickle.dumps(d)
>>> bs
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00tomq\x02X\x03\x00\x0
0\x00ageq\x03K\x12u.'

可以看到通过dumps()方法把对象序列化成bytes。接下来通过loads()方法将bytes反序列化成对象:

>>> pickle.loads(bs)
{'name': 'tom', 'age': 18}
  • 将对象序列化后写入文件:
>>> d = {'name': 'tom', 'age': 18}
>>> with open(r'Desktop\learn\test.txt', 'wb') as f:
...     pickle.dump(d, f)
...

对象序列化后写入文件用dump()方法,从文件中反序列化用load()方法:

>>> with open(r'Desktop\learn\test.txt', 'rb') as f:
...     pickle.load(f)
...
{'name': 'tom', 'age': 18}

这种序列化方式只能用于Python,可能不同版本的Python都不兼容,可以用它来保存一些不重要的数据。

2、JSON

JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,之后成了一种通用数据格式,可以被所有语言读取,方便地存储到磁盘、通过网络传输、直接在Web页面中读取、实现数据跨平台传输等。JSON的编码是UTF-8

相比pickleJSON就强大的多了,解决了pickle的问题,更加灵活方便。

Python中提供了 json模块来支持相关JSON操作。
首先导入json模块:

>>> import json
  • Python对象和JSON串相互转换:
>>> d = {'name': 'tom', 'age': 18}
>>> json.dumps(d)
'{"name": "tom", "age": 18}'

通过dumps()方法,将一个对象转换成JSON串,让然也可以通过loads()方法,将JSON串转换成Python对象:

>>> s = '{"name": "tom", "age": 18}'
>>> json.loads(s)
{'name': 'tom', 'age': 18}
  • 自定义类的对象序列化:
    先定义一个Cat类:
class Cat():
    def __init__(self, name, age):
        """初始化参数"""
        self.name = name
        self.age = age

默认情况下,dumps()方法不知道如何将Cat的对象转换成JSON,所以需要编写一个转换函数:

def cat2dict(cat):
    return {
        'name': cat.name,
        'age': cat.age
    }
>>> cat = Cat('tom', 2)
>>> json.dumps(cat, default=cat2dict)
'{"name": "tom", "age": 2}'

通常class类的实例都有一个__dict__属性,它是一个dict,用来存储实例变量,所以就有了序列化的捷径:

json.dumps(cat, default=lambda obj: obj.__dict__)
'{"name": "tom", "age": 2}'

当然也有少数类的实例没有__dict__属性,就不能使用这种方式了。

如果将JSON转换成Cat的对象,也需要编写一个转换函数:

def dict2cat(d):
    return Cat(d['name'], d['age'])
>>> s = '{"name": "tom", "age": 2}'
>>> json.loads(s, object_hook=dict2cat)
<__main__.Cat object at 0x000000000299DDA0>
  • 将对象序列化到文件:
>>> d = {'name': 'tom', 'age': 18}
>>> with open(r'Desktop\learn\test.txt', 'w') as f:
...     json.dump(d, f)
...

序列化到文件使用dump()方法,反序列化则使用load()方法:

>>> with open(r'Desktop\learn\test.txt', 'r') as f:
...     json.load(f)
...
{'name': 'tom', 'age': 18}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,573评论 18 139
  • IO编程概念 IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由C...
    时间之友阅读 719评论 0 0
  • 本文是笔者学习廖雪峰Python3教程的笔记,在此感谢廖老师的教程让我们这些初学者能够一步一步的进行下去.如果读者...
    相关函数阅读 1,462评论 2 9
  • 6月8日,康夏在他的微信公众号发布了也许是他有生之年在社交网络上公布的最后一篇文章(如果他果真不再以康夏的名义在网...
    林安阅读 12,539评论 2 6
  • 想像你走过这条路, 从这座城门穿过; 想像你沿着石阶走上独秀峰, 眺望这座陌生的城市; 想像你路过刀锋书店, 你翻...
    二月echo阅读 204评论 0 0