[关闭]
@Cleland 2019-09-26T01:18:23.000000Z 字数 7162 阅读 960

05 | Python文件存储

你好,我是悦创。

有时我们存储得到的数据,并不需要使用数据库存储。仅仅就需要存储成哪些常用的文本格式,供给其他人使用。

本文的主要内容:

序号 知识点
1 Python 操作文本
2 Python 操作二进制流
3 Python 操作 JSON(restful 风格)
4 Python 操作 Excel
5 Python 操作 World
1.OS 模块

日常操作文件,许多时候并不是操作有难题,而是路径问题。

Python 标准库-OS:https://docs.python.org/3/library/os.html

  1. import os
  2. file = 'D:\\Python_project'
  3. # 判断文件夹是否存在
  4. if not os.path.exists(file):
  5. # 不存在则创建
  6. os.mkdir(file)
  7. import os
  8. # 获取当前目录
  9. file_name = os.getcwd()
  10. txt = 'python.txt'
  11. with open(os.path.join(file_name, txt), 'w') as f:
  12. f.write('Hello world!')

我写了一个创建文件夹的插件:(切记,不要重复造轮子)

你可以自行调用。

  1. # -*- coding: utf-8 -*-
  2. # @Author :AI悦创
  3. # @DateTime :2019/9/16 16:08
  4. # @FileName :run_file.PY
  5. # @Function :功能
  6. # Development_tool :PyCharm
  7. import os
  8. import uuid
  9. def mkdir_file(path):
  10. path = path + r'\baidu_img'
  11. print(path)
  12. # 去除首位空格
  13. path = path.strip()
  14. # 去除尾部 \ 符号
  15. path = path.rstrip("\\")
  16. # 判断路径是否存在
  17. # 存在 True
  18. # 不存在 False
  19. isExists = os.path.exists(path)
  20. # 判断结果
  21. if not isExists:
  22. # 如果不存在则创建目录
  23. # 创建目录操作函数
  24. # os.makedirs(path)
  25. os.mkdir('baidu_img')
  26. os.mkdir(r'baidu_img\{}'.format(uuid.uuid4()))
  27. # print(path + ' 创建成功')
  28. return True
  29. else:
  30. # 如果目录存在则不创建,并提示目录已存在
  31. os.mkdir(r'baidu_img\{}'.format(uuid.uuid4()))
  32. return True
  33. if __name__ == '__main__':
  34. # 定义要创建的目录
  35. mkpath = os.path.dirname(__file__) #获取当前文件夹的绝对路径
  36. print(mkpath)
  37. # 调用函数
  38. mkdir_file(mkpath)

当然还有个轻便版本:

  1. def mk_dir():
  2. """
  3. 用于创建放置图片的文件夹
  4. :return: 文件夹名称
  5. """
  6. folder_name = input('请输入图片要存放的文件夹名称:>>> ')
  7. try:
  8. os.mkdir(r'{}'.format(folder_name))
  9. except FileExistsError:
  10. pass
  11. return folder_name
2.简化文件的起名方式

有时候,我们不想浪费时间给文件起名字,那我们有什么可以简化我们取名字的流程呢?

有时你会这么起名:

  1. index = 0
  2. for i in range(10):
  3. file_name = f'{i}.txt'
  4. print(file_name)
  5. index += 1
  6. # 输出
  7. 0.txt
  8. 1.txt
  9. 2.txt
  10. 3.txt
  11. 4.txt
  12. 5.txt
  13. 6.txt
  14. 7.txt
  15. 8.txt
  16. 9.txt
  17. [Finished in 0.2s]

还有一个更加 python 的方法 enumerate()

  1. for index, i in enumerate(range(10)):
  2. file_name = f'{index}.txt, text:{i}'
  3. print(file_name)
  4. # 输出
  5. 0.txt, text:0
  6. 1.txt, text:1
  7. 2.txt, text:2
  8. 3.txt, text:3
  9. 4.txt, text:4
  10. 5.txt, text:5
  11. 6.txt, text:6
  12. 7.txt, text:7
  13. 8.txt, text:8
  14. 9.txt, text:9
  15. [Finished in 0.1s]

剩下的就剩一个第三方库:UUID

  1. import uuid
  2. for i in range(10):
  3. file_name = '{uu}.txt, text:{i}'.format(uu=uuid.uuid4, i = i)
  4. print(file_name)
  5. # 输出
  6. <function uuid4 at 0x0000018B31031AF8>.txt, text:0
  7. <function uuid4 at 0x0000018B31031AF8>.txt, text:1
  8. <function uuid4 at 0x0000018B31031AF8>.txt, text:2
  9. <function uuid4 at 0x0000018B31031AF8>.txt, text:3
  10. <function uuid4 at 0x0000018B31031AF8>.txt, text:4
  11. <function uuid4 at 0x0000018B31031AF8>.txt, text:5
  12. <function uuid4 at 0x0000018B31031AF8>.txt, text:6
  13. <function uuid4 at 0x0000018B31031AF8>.txt, text:7
  14. <function uuid4 at 0x0000018B31031AF8>.txt, text:8
  15. <function uuid4 at 0x0000018B31031AF8>.txt, text:9
  16. [Finished in 0.2s]

这一部分,我主要给你讲 uuid 库的使用

  1. import uuid
  2. from uuid import UUID
  3. # 基于时间戳
  4. print(uuid.uuid1())
  5. # 基于名字的MD5散列
  6. print(uuid.uuid3(UUID(int=9), "lvv"))
  7. # 基于随机数
  8. print(uuid.uuid4())
  9. # 基于名字的SHA-1散列
  10. print(uuid.uuid5(UUID(int=9), "lvv"))

Ps:当需要大批量下载图片或者文档的时候可以使用 UUID

3. Python 文件操作

一下知识点以此代码作为示例,最后输出结果显示在第三列。

  1. with open('test.txt', '模式', encoding='utf8') as f:
  2. res = f.readable()
  3. print(f'readable:>>>{res}')
关键词(模式) 作用 输出结果
r 读取文件(只读模式) True
w 创建文件,会覆盖源文件 False
(只写模式【不可读,不存在则创建,存在则删除文件中的内容】) False
a 追加文件,不存在会创建......(没什么卵用) False
【不可读,不存在则创建,存在则只追加内容】
b 操作二进制流 False
+ rw 的集合(表示可以同时学习某个文件)
r+ 可读写文件【可读、可写、可追加】 True
w+ 写读 True
U U表示在读取时,可以将\r \n \r\n自动转换成\n

首先我们需要先了解一下,计算机中文件访问的基础知识。事实上,计算机内核(kernel)对文件的处理相对比较复杂,涉及到内核模式、虚拟文件系统、锁和指针等一系列概念,这些内容我不会深入讲解,我只说一些基础但足够使用的知识。

我们先要用open() 函数拿到文件的指针。其中,第一个参数指定文件位置(相对位置或者绝对位置);第二个参数,如果是 'r'表示读取,如果是'w' 则表示写入,当然也可以用 'rw' ,表示读写都要。a 则是一个不太常用(但也很有用)的参数,表示追加(append),这样打开的文件,如果需要写入,会从原始文件的最末尾开始写入。

这里我插一句,在实际的工作中,代码权限管理非常重要。如果你只需要读取文件,就不要请求写入权限。这样在某种程度上可以降低 bug 对整个系统带来的风险。

a+ 代替 wfor 循环不得不写在 write 函数之外时候适用

  1. with open('test.txt', 'a+') as f:
  2. f.write('Python'.encode())

文件有开启,就有关闭。

你或许想用下面的方法来读取文件:

  1. text = "Hello World!"
  2. f = open('text.txt', 'w')
  3. f.write(text)
  4. f.close()

我个人更喜欢第一种方法,更加的 Python 程序员,而且 with 方法,可以有效防止你文件操作后,忘记关闭。造成占用内存或者内存溢出。

接下来,我来给你详细的说一说:

  1. with open('test.txt', 'wb') as f:
  2. text = f.read()
  3. f.write('Python'.encode())

上面的代码并不能正常运行,只是提供例子。以下示例是可以正常运行的:

  1. with open('test.txt', 'wb') as f:
  2. f.write('Python'.encode())
  3. with open('test.txt', 'w', encoding='utf8') as f:
  4. f.write('Python')

运行程序之后会在当前文件夹下生成 test.txt 文件,那读取操作呢?

  1. with open('test.txt', 'r', encoding='utf8') as f:
  2. res = f.read()
  3. print(res)
  4. # 输出
  5. Python

接下来,我来补充一些:

关于 with open 公众号往期文章中有哦!

在拿到指针后,我们可以通过 read() 函数,来读取文件的全部内容。代码 text = f.read() ,即表示把文件所有内容读取到内存中,并赋值给变量 text。

这么做自然也是有利有弊:

  1. 优点是方便,接下来我们可以很方便地调用 parse 函数进行分析;
  2. 缺点是如果文件过大,一次性读取可能造成内存崩溃。
  3. 这时,我们可以给 read 指定参数 size ,用来表示读取的最大长度。还可以通过 readline() 函数,每次读取一行,这种做法常用于数据挖掘(Data Mining)中的数据清洗,在写一些小的程序时非常轻便。如果每行之间没有关联,这种做法也可以降低内存的压力。而 write() 函数,可以把参数中的字符串输出到文件中,也很容易理解。
  4. 这里我需要简单提一下 with 语句(后文会详细讲到)。open() 函数对应于 close() 函数,也就是说,如果你打开了文件,在完成读取任务后,就应该立刻关掉它。而如果你使用了 with 语句,就不需要显式调用 close()。在 with 的语境下任务执行完毕后,close() 函数会被自动调用,代码也简洁很多。
  5. 这里我想多说几句,关于 readline() 与 readlines()
readline() 读取行
readlines() 读取所有行(得到的数据是给列表)
readable() 判断能否读取

示例:

比如我们现在有以下的文本你内容

  1. Python
  2. AI悦创-创造不同
  3. 公众号:AI悦创
  4. 欢迎关注!

我们来实际读取一下:

  1. with open('test.txt', 'r', encoding='utf8') as f:
  2. res1 = f.readline()
  3. res2 = f.readlines()
  4. print(f'readline:>>>{res1}')
  5. print(f'readlines:>>>{res2}')
  6. # 输出
  7. readline:>>>Python
  8. readlines:>>>['AI悦创-创造不同\n', '公众号:AI悦创\n', '欢迎关注!']
4. 小块读取
  1. import requests,uuid
  2. def get_img(url, headers):
  3. img = requests.get(url, stream = True, headers = headers)
  4. img_name = '{}.jpg'.format(uuid.uuid4())
  5. with open(img_name, 'wb') as f:
  6. chunks = img.iter_content(chunk_size=128)# 单位是字节
  7. for chunk in chunks:
  8. f.write(chunk)
  9. headers = {
  10. 'Referer': 'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fr=&sf=1&fmq=1567133149621_R&pv=&ic=0&nc=1&z=0&hd=0&latest=0&copyright=0&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E5%A3%81%E7%BA%B8',
  11. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
  12. 'X-Requested-With': 'XMLHttpRequest', }
  13. if __name__ == '__main__':
  14. url = 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=316485425,4089915232&fm=26&gp=0.jpg'
  15. get_img(url,headers)

小块读取:避免一次性占满内存,减轻 CPU 压力,在读取大文件时候很有优势。

如果你电脑内存大的话,可以忽略这个小块传输。

5. Python 操作 Json

Json (JavaScript Object Notation) 是一种轻量级的数据交换格式。Json 采用完全独立于语言的文本格式,这些特性使 Json 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

  1. data:{
  2. "people":[{
  3. "firstName":"Brett",
  4. "lastName":"Mclaughlin",
  5. "email":"aaa"
  6. },{
  7. "firstName":"Jason",
  8. "lastName":"Hunter",
  9. "email":"bbb"
  10. },{
  11. "firstName":"Elliotte",
  12. "lastName":'Harold',
  13. "email":"ccc"
  14. }]
  15. }

比如,我要获取其中的 firstName:Jason,该如何获取呢?

  1. data["people"][1]["firstName"]

Ps:Json 只能使用英文输入法下的“双引号”

  1. # json.dumps() 与 json.dump()
  2. import json
  3. data = {
  4. "name":"AI悦创",
  5. "shares":100,
  6. "price":542.23
  7. }
  8. # 操作一
  9. # 把字典转换成 json
  10. res = json.dumps(data)
  11. # json.dumps() 需要加 s 否则将写入成为文件(但也不是这么编写的,下面有示例)
  12. print(res)
  13. print(type(res))
  14. # 输出
  15. {"name": "AI\u60a6\u521b", "shares": 100, "price": 542.23}
  16. <class 'str'>
  17. # 操作二
  18. with open('data.json', 'w') as f:
  19. json.dump(data, f)
  20. # 输出
  21. 保存成 json 格式文件,自行运行尝试
  22. # json.loads() 与 json.load()
  23. import json
  24. data = '{"name":"AI月悦创","shares":100,"price":542.23}'
  25. # 操作一
  26. res = json.loads(data)
  27. print(res)
  28. print(type(res))
  29. # 输出
  30. {'name': 'AI月悦创', 'shares': 100, 'price': 542.23}
  31. <class 'dict'>
  32. # 操作二
  33. # data.json 文件中的内容:
  34. # --------------------
  35. {"name": "AI\u60a6\u521b", "shares": 100, "price": 542.23, "Love": 1314}
  36. # -----------------------------------
  37. with open('data.json', 'r') as f:
  38. data = json.load(f)
  39. print(data)
  40. print(type(data))
  41. # 输出
  42. {'name': 'AI悦创', 'shares': 100, 'price': 542.23, 'Love': 1314}
  43. <class 'dict'>

Json 模块提供了简单的编码 Json 格式的方法,主要是 json.dumps() 和 json.loads()

接口很少

而 json.dump() 和 json.load() 适用于写入文件的时候。

fp:代表文件

函数 作用
json.dump() 写入到文件
json.dumps() 将 Python 对象编码成 JSON 字符串(写入到字符串)
json.load()
json.loads() 将已编码的 JSON 字符串解码为 Python 对象
识记 以 s 为结尾的都是以 Terminal (命令行)交互

dump的功能就是把 Python 对象 encode 为 json 对象,一个编码过程。注意json模块提供了 json.dumpsjson.dump 方法,区别是 dump 直接到文件,而 dumps 到一个字符串,这里的 s 可以理解为 string

前面两个是 Python 转换到 json (dumps 与 dump)

后面两个是 Json 转换到 Python (loads 与 load)


6. 腾讯新闻案例
此处输入代码
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注