python-book
  • 目录
  • 第2章 Python基础 (旧版)
    • 2.1 上节拾遗
    • 2.2 二进制
    • 2.3 字符编码
    • 2.4 基本数据类型——数字
    • 2.5 基本数据类型——字符串
    • 2.6 基本数据类型——列表
    • 2.7 基本数据类型——元组
    • 2.8 可变、不可变数据类型和hash
    • 2.9 基本数据类型——字典
    • 2.10 基本数据类型——集合
    • 2.11 collections模块
    • 2.12 本章小结
      • 习题答案
  • 第3章 Python基础—文件操作&函数(旧版)
    • 3.1 上节拾遗
    • 3.2 三元运算
    • 3.3 字符编码转换
    • 3.4 文件处理
    • 3.5 函数
    • 3.6 函数进阶
    • 3.7 生成器&迭代器
    • 3.8 本章小节
      • 习题答案
  • 第4章 Python基础—常用模块(旧版)
    • 4.1 模块、包介绍和相关语法
    • 4.2 time & datetime 模块
    • 4.3 random 模块
    • 4.4 os 模块
    • 4.5 sys 模块
    • 4.6 shutil 模块
    • 4.7 json & pickle 模块
    • 4.8 shelve 模块
    • 4.9 xml 模块
    • 4.10 ConfigParser 模块
    • 4.11 hashlib 模块
    • 4.12 subprocess 模块
    • 4.13 logging 模块
      • python日志重复输出
    • 4.14 re 模块
    • 4.15 软件开发目录规范
    • 4.16 本章小结
      • 习题答案
  • 第5章 面向对象编程设计与开发
    • 面向对象介绍
    • 类、实例、属性、方法详解
    • 5.1 什么是面向对象的程序设计
    • 5.2 类与对象
    • 5.3 属性查找与绑定方法
    • 5.4 小结
    • 5.5 继承与派生
    • 5.6 组合
    • 5.7 抽象类
    • 5.8 多态与多态性
    • 5.9 封装
    • 5.10 绑定方法与非绑定方法
    • 5.11 内置方法
    • 5.11 内置方法(补充)
    • 5.12 元类
    • 5.13 面向对象的软件开发
    • 5.14 领域模型
    • 5.15 异常处理
    • 5.16 本章总结
  • 第6章 网络编程-SOCKET开发
    • 6.1 C/S架构介绍
    • 6.2 TCP/IP 各层详解
    • 6.3 Socket介绍
    • 6.4 Socket代码实例
    • 6.5 粘包现象与解决方案
    • 6.6 通过socket发送文件
    • 6.7 本章总结
  • 第7章 并发编程
    • 7.1 操作系统介绍
      • 附录1:操作系统介绍
    • 7.2 并发编程之多进程
      • 7.2.1 进程理论
      • 7.2.2 开启进程的两种方式
      • 7.2.3 join方法
      • 7.2.4 守护进程
      • 7.2.5 互斥锁
      • 7.2.6 队列
      • 7.2.7 生产者消费者模型
    • 7.3 并发编程之多线程
      • 7.3.1 线程理论
      • 7.3.2 开启线程的两种方式
      • 7.3.3 多线程与多进程的区别
      • 7.3.4 Thread对象的其他属性或方法
      • 7.3.5 守护线程
      • 7.4.6 GIL全局解释器锁
      • 7.4.7 死锁现象与递归锁
      • 7.4.8 信号量,Event,定时器
      • 7.4.9 线程queue
      • 7.4.10 进程池与线程池
    • 7.4 并发编程之协程
      • 7.4.1 协程介绍
      • 7.4.2 greenlet模块
      • 7.4.3 gevent模块
    • 7.5 IO模型
      • 7.5.1 IO模型介绍
      • 7.5.2 阻塞IO
      • 7.5.3 非阻塞IO
      • 7.5.4 多路复用IO
      • 7.5.5 异步IO
      • 7.5.6 IO模型比较分析
      • 7.5.7 selectors模块
    • 7.6 本章小结
  • 第8章 MySQL数据库
    • 8.1 初识数据库
      • 8.1.1 数据库管理软件的由来
      • 8.1.2 数据库概述
      • 8.1.3 mysql安装与基本管理
      • 8.1.4 初识sql语句
    • 8.2 库操作
      • 8.2.1 库的增删改查
    • 8.3 表操作
      • 8.3.1 存储引擎介绍
      • 8.3.2 表的增删改查
      • 8.3.3 数据类型
        • 1 数值类型
        • 2 日期类型
        • 3 字符串类型
        • 4 枚举类型与集合类型
      • 8.3.4 完整性约束
    • 8.4 数据操作
      • 8.4.1 数据的增删改
      • 8.4.2 单表查询
      • 8.4.3 多表查询
    • 8.5 Navicat工具与pymysql模块
      • 8.5.1 图形工具Navicat
      • 8.5.2 pymysql模块
    • 8.6 mysql内置功能
      • 8.6.1 视图
      • 8.6.2 触发器
      • 8.6.3 事务
      • 8.6.4 存储过程
      • 8.6.5 函数
      • 8.6.6 流程控制
    • 8.7 索引原理与慢查询优化
      • 8.7.1 索引原理与慢查询优化(1)
      • 8.7.2 索引原理与慢查询优化(2)
    • 8.8 本章小结
      • 8.8.1 章节作业
  • 第9章 前端开发
    • 9.0 前端内容介绍
      • 前端究竟是个什么鬼?
    • 9.1 HTML
      • 9.1.1 HTML简介
      • 9.1.2 开发环境
      • 9.1.3 HTML标签介绍
      • 9.1.4 HTML文档结构(重点)
      • 9.1.5 HTML注释
      • 9.1.6 head标签相关内容
      • 9.1.7 body标签相关内容(重点)
        • 常用标签一
        • 常用标签二
      • 9.1.8 HTML标签属性
      • 9.1.9 HTML标签分类(重点)
      • 9.1.10 标签嵌套规则(重点)
      • 9.1.11 HTML练习题
    • 9.2 CSS
      • 9.2.1 CSS介绍
      • 9.2.2 CSS语法
      • 9.2.3 CSS引入方式
      • 9.2.4 基本选择器
      • 9.2.5 组合选择器
      • 9.2.6 属性选择器
      • 9.2.7 分组选择器
      • 9.2.8 伪类选择器
      • 9.2.9 伪元素选择器
      • 9.2.10 选择器的优先级(重点)
      • 9.2.11 字体属性
      • 9.2.12 文字属性
      • 9.2.13 背景属性
      • 9.2.14 display属性(重点)
      • 9.2.15 盒模型(重点)
      • 9.2.16 浮动与清除浮动(重点)
      • 9.2.17 background属性(侧重点)
      • 9.2.18 定位(重点)
      • 9.2.19 z-index(重点)
      • 9.2.20 css练习题
    • 9.3 JavaScript
      • 9.3.1 JavaScript简介
      • 9.3.2 ECMAScript 5.0
      • 9.3.3 正则表达式
      • 9.3.4 DOM(重点)
      • 9.3.5 client、offset、scroll系列
      • 9.3.6 定时器
      • 9.3.7 BOM
      • 9.3.8 练习题
    • 9.4 jQuery
      • 9.4.1使用js的一些疼处
      • 9.4.2 js和jquery的区别
      • 9.4.3 jquery文件的引入
      • 9.4.4 jquery选择器用法
      • 9.4.5 jquery对象和DOM对象的转换
      • 9.4.6 jquery的效果
      • 9.4.7 jquery的属性操作
      • 9.4.8 操作input的value值
      • 9.4.9 jquery文档操作
      • 9.4.10 jquery的CSS
      • 9.4.11 jquery的筛选方法
      • 9.4.12 jquery的事件
      • 9.4.13 jquery的Ajax
      • 9.4.14 补充内容
      • 9.4.15 练习题
    • 9.5 Bootstrap
      • 9.5.1 Bootstrap的介绍和响应式@metia媒体查询
      • 9.5.2 Bootstrap的引入和使用
      • 9.5.3 Bootstrap插件的一些常用属性介绍
    • 9.6 前端内容流程导图
  • 第10章 Django
    • 10.1 web应用与http协议
      • 10.1.1 web应用与web框架
    • 10.2 http协议简介
    • 10.3 Django简介
    • 10.4 Django-2的路由层(URLconf)
    • 10.5 Django的视图层
    • 10.6 Django模板层
    • 10.7 Django模型层
      • 模型层一单表操作
      • 模型层二多表操作
    • 10.8 Django组件-cookie与session
    • 10.9 Django组件-forms组件
    • 10.10 Django组件-用户认证
    • 10.11 Django组件-中间件
    • 10.12 Django组件-分页器
    • 10.13 Django与Ajax
    • 10.14习题
  • 第11章 BBS项目(博客系统)
    • 11.1 基于Ajax和用户认证系统的登录验证
    • 11.2 基于Ajax和forms组件的实现注册功能
    • 11.3 系统首页的布局渲染
    • 11.4 个人站点的文章,标签,分类查询
    • 11.5 文章详细页的设计
    • 11.6 点赞与踩灭功能的实现
    • 11.7 评论功能的实现
    • 11.8 基于富文本编辑器框和beautifulSoup模块防止xss攻击
  • 第12章 CRM项目
    • 12.1 权限组件之权限控制
  • 第1章 Python基础(旧版)
    • 1.1 编程语言介绍
    • 1.2 Python介绍
    • 1.3 Python安装
    • 1.4 第一个Python程序
    • 1.5 变量
    • 1.6 程序交互
    • 1.7 基本数据类型
    • 1.8 格式化输出
    • 1.9 基本运算符
    • 1.10 流程控制之 if ... else
    • 1.11 流程控制之 循环
    • 1.12 开发工具IDE
    • 1.13 本章小节
      • 习题答案
    • 1.14 Python开发规范指南
      • 1.14.1 Python风格规范
      • 1.14.2 Python语言规范
  • 第1章 Python基础语法(new)
    • 1.1 编程语言介绍与分类
    • 1.2 Python介绍、发展趋势
    • 1.3 Python环境安装
    • 1.4 开发你的第一个Python程序
    • 1.5 选择最好用的PyCharm IDE
    • 1.6 变量
    • 1.7 注释
    • 1.8 基本数据类型
    • 1.9 读取用户指令
    • 1.10 格式化打印
    • 1.11 运算符
    • 1.12 流程控制之if...else
    • 1.13 流程控制之while循环
    • 1.14 本章练习题&作业
  • 第2章 Python基础-数据类型和文件操作(new)
    • 2.1 上章补充-Bytes类型
  • 第3章 Python基础-函数编程(new)
  • 第4章 Python基础 常用模块(new)
Powered by GitBook
On this page
  • 本节重点:
  • 引子
  • Python处理文件
  • 读文件
  • 循环文件
  • 写文件
  • 追加
  • 读写模式
  • 文件操作的其它功能
  • 修改文件
  • 练习题

Was this helpful?

  1. 第3章 Python基础—文件操作&函数(旧版)

3.4 文件处理

本节重点:

  • 使学生掌握文件的读、写、修改方法

  • 掌握文件处理模式的区别

本节时长需控制在50分钟内

引子

1.问题:给你一个文件 "兼职白领学生空姐模特护士联系方式.txt" ,如何查看内容?

答:

  1. 安装文本编辑器软件

  2. 选中右键,利用文本编辑器软件打开

  3. 查看 or 写入

  4. 保存,关闭

PS: 看到居然还有xxx的女朋友 或 美好的事物应该分享,默默的把xxx的女朋友电话也写进去

2.问题:文件在硬盘上是如何存储?

答:以某种编码格式的 “010101010101001” 保存在硬盘上。

3.问题:假定世上无文本编辑器软件,如何使用Python对文件进行操作?

答:请看下面

Python处理文件

文件操作分为读、写、修改,我们先从读开始学习

读文件

示例1:

f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='r',encoding='utf-8')

data = f.read()

f.close()

上述操作语法解释:

file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'  表示文件路径
mode='r'                                          表示只读(可以修改为其他)
encoding='utf-8'                                  表示将硬盘上的 0101010 按照utf-8的规则去“断句”,再将“断句”后的每一段0101010转换成unicode的 01010101,unicode对照表中有01010101和字符的对应关系。
f.read()                                          表示读取所有内容,内容是已经转换完毕的字符串。
f.close()                                         表示关闭文件

PS: 此处的encoding必须和文件在保存时设置的编码一致,不然“断句”会不准确从而造成乱码。

示例2:

f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='rb')
data = f.read()
f.close()

上述操作语法解释:

file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'      表示文件路径
mode='rb'                                            表示只读(可以修改为其他)
f.read()                                             表示读取所有内容,内容是硬盘上原来以某种编码保存的 010101010,即:某种编码格式的字节类型
f.close()                                            表示关闭文件

问:示例2和示例1的区别在哪?

答:在于示例2打开文件时并未指定encoding,这是为何?是因为直接以rb模式打开了文件 ,rb是指二进制模式,数据读到内存里直接是bytes格式,如果想内容,还需要手动decode,因此在文件打开阶段,不需要指定编码

问:假如你不知道你要处理的文件是什么编码可怎么办呢?

import chardet

f = open('log',mode='rb')
data = f.read()
f.close()

result = chardet.detect(open('log',mode='rb').read())
print(result)

输出:

{'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}

注意:

  • 文件操作时,以 “r”或“rb” 模式打开,则只能读,无法写入;

  • 硬盘上保存的文件都是某种编码的0101010,打开时需要注意:

    • rb,直接读取文件保存时原生的0101010,在Python中用字节类型表示

    • r和encoding,读取硬盘的0101010,并按照encoding指定的编码格式进行断句,再将“断句”后的每一段0101010转换成unicode的 010101010101,在Python中用字符串类型表示

循环文件

f = open("兼职白领学生空姐模特护士联系方式.txt",'r',encoding="utf-8")

for line in f:
    print(line)

f.close()

写文件

f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='w',encoding='utf-8')
f.write('北大本科美国留学一次50,微信号:xxxxx')
f.close()

上术操作语法解释:

file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'     表示文件路径
mode='w'                                             表示只写
encoding='utf-8'                                     将要写入的unicode字符串编码成utf-8格式
f.write(...)                                         表示写入内容,写入的内容是unicode字符串类型,内部会根据encoding转换为制定编码的 01101010101,即:字节类型
f.close()

二进制写

f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='wb')
f.write('北大本科美国留学一次50,微信号:xxxxx'.encode('utf-8'))
f.close()

上述操作语法解释:

file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'      表示文件路径
mode='wb'                                             表示只以2进制模式写
f.write(...)                                          表示写入内容,写入的内容必须字节类型,即:是某种编码格式的0101010
f.close()

注意:

文件操作时,以 “w”或“wb” 模式打开,则只能写,并且在打开的同时会先将内容清空。

写入到硬盘上时,必须是某种编码的0101010,打开时需要注意:

  • wb,写入时需要直接传入以某种编码的0100101,即:字节类型

  • w 和 encoding,写入时需要传入unicode字符串,内部会根据encoding制定的编码将unicode字符串转换为该编码的 010101010

追加

把内容追加到文件尾部

f = open("兼职白领学生空姐模特护士联系方式.txt",'a',encoding="gbk")

f.write("\n杜姗姗 北京  167 49 13324523342")
f.close()

运行结果

姓名        地区    身高    体重    电话
况咏蜜     北京    171    48    13651054608
......
岳妮妮     深圳    177    54    18835324553
贺婉萱     深圳    174    52    18933434452
叶梓萱    上海    171    49    18042432324
杜姗姗 北京  167 49 13324523342   #这行是添加的

注意:

文件操作时,以 “a”或“ab” 模式打开,则只能追加,即:在原来内容的尾部追加内容

写入到硬盘上时,必须是某种编码的0101010,打开时需要注意:

  • ab,写入时需要直接传入以某种编码的0100101,即:字节类型

  • a 和 encoding,写入时需要传入unicode字符串,内部会根据encoding制定的编码将unicode字符串转换为该编码的 010101010

读写模式

打开模式只有只读、只写、只追加,难道没有可以读写的操作吗?当然有

读写模式

f = open("兼职白领学生空姐模特护士联系方式.txt",'r+',encoding="gbk")
data = f.read() #可以读内容 
print(data)
f.write("\nblack girl  河北  167 50  13542342233") #可以写
f.close()

但上面的内容写到哪个位置了呢?答案是追加到了最后面。

那如果是我想添加到任意位置呢?答案是可以,又是不可以。。。。,为啥,一会就学

写读模式

f = open("兼职白领学生空姐模特护士联系方式.txt",'w+',encoding="gbk")
data = f.read() 
print(data)

f.write("\nnewline 1哈哈")
f.write("\nnewline 2哈哈")
f.write("\nnewline 3哈哈")
f.write("\nnewline 4哈哈")

print("content",f.read())

f.close()

输出

         #注意这是个空行, 是上面print(data)的结果,代表 根本 没读到内容
content  #从这开始,读到的是刚写入的内容
newline 1哈哈
newline 2哈哈
newline 3哈哈
newline 4哈哈

此时查看文件 内容 发现,里面只有4条newline..内容,之前的旧内容全没了,事实代表,w+会先把文件清空,再写新内容,相比w模式,只是支持了一个读功能,且还只能读已经写入的新内容。着实没什么卵用。。。

文件操作的其它功能

    def fileno(self, *args, **kwargs): # real signature unknown
        返回文件句柄在内核中的索引值,以后做IO多路复用时可以用到

    def flush(self, *args, **kwargs): # real signature unknown
        把文件从内存buffer里强制刷新到硬盘

    def readable(self, *args, **kwargs): # real signature unknown
        判断是否可读

    def readline(self, *args, **kwargs): # real signature unknown
        只读一行,遇到\r or \n为止

    def seek(self, *args, **kwargs): # real signature unknown
        把操作文件的光标移到指定位置
        *注意seek的长度是按字节算的, 字符编码存每个字符所占的字节长度不一样。
        如“路飞学城” 用gbk存是2个字节一个字,用utf-8就是3个字节,因此以gbk打开时,seek(4) 就把光标切换到了“飞”和“学”两个字中间。
        但如果是utf8,seek(4)会导致,拿到了飞这个字的一部分字节,打印的话会报错,因为处理剩下的文本时发现用utf8处理不了了,因为编码对不上了。少了一个字节

    def seekable(self, *args, **kwargs): # real signature unknown
        判断文件是否可进行seek操作

    def tell(self, *args, **kwargs): # real signature unknown
        返回当前文件操作光标位置 

    def truncate(self, *args, **kwargs): # real signature unknown
        按指定长度截断文件
        *指定长度的话,就从文件开头开始截断指定长度,不指定长度的话,就从当前位置到文件尾部的内容全去掉。

    def writable(self, *args, **kwargs): # real signature unknown
        判断文件是否可写

每个都举例试一下。

现在提出一个萦绕心头的问题,文件内容是否可修改?当然可以,但需要套路

修改文件

尝试直接以r+模式打开文件,默认会把新增的内容追加到文件最后面。但我想要的是修改中间的内容 ,怎么办? 为什么会把内容添加到尾部呢?(最新测试r+会从头覆盖,测试代码如下)

f1 = open("luffy.txt",'w',encoding="utf-8")

f1.write("[路飞学城]")

f1.close()

f = open("luffy.txt",'r+',encoding="utf-8")

f.write("alex")

f.close()

我们已经学了seek,现在告诉你,之所以内容会追加到最后面,是因为,文件一打开,要写的时候,光标会默认移到文件尾部,再开始写。 现在我想修改中间部分,是不是seek(中间位置)再写就可以了呢?

f = open("兼职白领学生空姐模特护士联系方式utf8.txt",'r+',encoding="utf-8")

f.seek(6)

f.write("[路飞学城]")

f.close()

执行没报错,开心,看输出

王心[路飞学城]9    46    13813234424
马纤羽     深圳    173    50    13744234523
乔亦菲     广州    172    52    15823423525
罗梦竹     北京    175    49    18623423421
刘诺涵     北京    170    48    18623423765
岳妮妮     深圳    177    54    18835324553
贺婉萱     深圳    174    52    18933434452
叶梓萱    上海    171    49    18042432324
杜姗姗 北京  167 49 13324523342
black girl  河北  167 50  13542342233

确实从第3个字开始改的,但是我擦,好像我的[路飞学城] 把后面的内容覆盖啦。。。。,这不是我想要的呀。。。

问:为什么这样子?

这是硬盘的存储原理导致的,当你把文件存到硬盘上,就在硬盘上划了一块空间,存数据,等你下次打开这个文件 ,seek到一个位置,每改一个字,就是把原来的覆盖掉,如果要插入,是不可能的,因为后面的数据在硬盘上不会整体向后移。所以就出现 当前这个情况 ,你想插入,却变成了会把旧内容覆盖掉。

问:但是人家word, vim 都可以修改文件 呀,你这不能修改算个什么玩意?

我并没说就不能修改了,你想修改当然可以,就是不要在硬盘上修改,把内容全部读到内存里,数据在内存里可以随便增删改查,修改之后,把内容再全部写回硬盘,把原来的数据全部覆盖掉。vim word等各种文本编辑器都是这么干的。

问:说的好像有道理,但你又没看过word软件的源码,你凭什么这么笃定?

哈哈,我不需要看源码,硬盘 的存储原理决定了word必须这么干 ,不信的话,还有个简单的办法来确认我说的,就是用word or vim读一个编辑一个大文件 ,至少几百MB的,你 会发现,加载过程会花个数十秒,这段时间干嘛了? cpu 去玩了?去上厕所啦? 当然不是,是在努力把数据 从硬盘上读到内存里。

问:但是文件如果特别大,比如5个GB,读到内存,就一下子吃掉了5GB内存,好费资源呀,有没有更好的办法呢?

如果不想占内存,只能用另外一种办法啦,就是边读边改, 什么意思? 不是不能改么?是不能改原文件 ,但你可以打开旧文件 的同时,生成一个新文件呀,边从旧的里面一行行的读,边往新的一行行写,遇到需要修改就改了再写到新文件 ,这样,在内存里一直只存一行内容。就不占内存了。 但这样也有一个缺点,就是虽然不占内存 ,但是占硬盘,每次修改,都要生成一份新文件,虽然改完后,可以把旧的覆盖掉,但在改的过程中,还是有2份数据 的。

问:还有更好的方式 么?

有完没完? 没了。

占硬盘方式的文件修改代码示例

f_name = "兼职白领学生空姐模特护士联系方式utf8.txt"
f_new_name = "%s.new" % f_name

old_str = "乔亦菲"
new_str = "[乔亦菲 Yifei Qiao]"

f = open(f_name,'r',encoding="utf-8")
f_new = open(f_new_name,'w',encoding="utf-8")

for line in f:

    if old_str in line:
        new_line = line.replace(old_str,new_str)
    else:
        new_line = line

    f_new.write(new_line)

f.close()
f_new.close()

上面的代码,会生成一个修改后的新文件 ,原文件不动,若想覆盖原文件

import os

f_name = "兼职白领学生空姐模特护士联系方式utf8.txt"
f_new_name = "%s.new" % f_name

old_str = "乔亦菲"
new_str = "[乔亦菲 Yifei Qiao]"

f = open(f_name,'r',encoding="utf-8")
f_new = open(f_new_name,'w',encoding="utf-8")

for line in f:

    if old_str in line:
        new_line = line.replace(old_str,new_str)
    else:
        new_line = line

    f_new.write(new_line)

f.close()
f_new.close()

os.rename(f_new_name,f_name) #把新文件名字改成原文件 的名字,就把之前的覆盖掉了,windows使用os.replace # 帮助文档说明replace会覆盖原文件

练习题

练习题1 —— 全局替换程序:

  • 写一个脚本,允许用户按以下方式执行时,即可以对指定文件内容进行全局替换

      `python your_script.py old_str new_str filename`
  • 替换完毕后打印替换了多少处内容

练习题2 —— 模拟登陆:

  • 用户输入帐号密码进行登陆

  • 用户信息保存在文件内

  • 用户密码输入错误三次后锁定用户,下次再登录,检测到是这个用户也登录不了

Previous3.3 字符编码转换Next3.5 函数

Last updated 5 years ago

Was this helpful?