本学习笔记正在编辑中……
CSV文件格式——方便好用个头最小的数据传递方式
CSV是什么?先搜搜😋
中文名 CSV,外文名 Comma Separated Values,别名“逗号分隔值”。应用,在程序之间转移表格数据。用法、规则,请点击文字跳转阅读。
明白了 CSV 结构,就来炼炼 CSV 的读写。先写后读。
模块加载,先全部加载本练习将要用到的功能模块。按python“约定”,按先内置后三方再自制的顺序加载。
from time import sleep # 加载time模块暂停方法。
import csv # 载入python 内置模块。
from os import system # 加载Linux命令容器,方便用代码执行Linux命令。
from random import choice # 加载随机数模块随机选择方法。
import pickle # 加载python“私有”二进制序列化对象到字符串,方便写入磁盘文档存储。
import json # 加载json二进制序列化对象到字符串,方便写入磁盘文档存储。
from python_color import color # 加载自制色彩控制打印工具模块。
import color_tip # 加载“七彩提示字符串展示”工具
s = ' 正在加载Pandas…… ' # pandas 加载太慢,放了个“七彩提示”,所以“违规”后移了。😄
color_tip.show_tip(s, 6, 55) # 工具展示提示字符串。
import pandas as pd # 加载pandas,用其DataFrame框架展示csv数据,是很好的选择。
试炼数据
s = '''
昵称,性别,现居地,是否单身,爱好
梦幻精灵_cq,男,重庆巴南,否,Python
多儿,男,多邻国,是,English
'''
要保存的 csv 文件路径:
filename = r'/scard/001/demo_csv.txt'
在后面的例子中,经常会 (用 Linux 命令) 查看文件信息及内容,所以先写个函数。
def cat(filename):
''' 文件查看,在 python 环境中没有关键字“cat”,所以本函数直接用 Linux 文件查看命令 cat 命名。 '''
print(f"\n创建的 csv 文件 “{filename}” 信息及内容:\n")
system(f'ls -l {filename}')
print(color(1, 'f_green')) # 色彩控制起。
system(f'cat {filename}')
print(color(0)) # 色彩控制止。
我的当前目录是“/sdcard/qpython/”,要创建的csv把文件存储在“/sdcard/001/”。运行代码是’/sdcard/qpython/'目录,*.py 文件所在目录即为该代码文件运行环境时域的“当前目录”。交待清楚这个,是有助于看清我代码中的相对路径。我喜欢用相对路径,方便、且支持可无缝移植。
f = open(filename, 'w') # 创建文件。
f.write('昵称,性别,现居地,是否单身,爱好')
f.write('\n')
f.write('梦幻精灵_cq,男,重庆巴南,否,Python')
f.write('\n')
f.write('多儿,男,多邻国,是,English')
f.write('\n')
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
效果图写入失败截屏

用常规写法 (open(filename, ‘w’),如果忘记关闭文件 (f.close()),就会创建一个空白文件。因为 python open(filename, ‘w’) 写入文件的内容,是驻留在内存中的,只有在 f.close() 后才真正写入磁盘文件。
f = open(filename, 'w') # 创建文件。
f.write('昵称,性别,现居地,是否单身,爱好')
f.write('\n')
f.write('梦幻精灵_cq,男,重庆巴南,否,Python')
f.write('\n')
f.write('多儿,男,多邻国,是,English')
f.write('\n')
#f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
效果图

加入 f.close() 关闭文件后,写入内容成功保存在 csv 文件中了。
变量写入,代码更简洁
print('字符串处理数据写入:')
f = open(filename, 'w') # 创建文件。
f.write(data_in_rows[0]) # 第一行字符串写入。
f.write('\n')
f.write(data_in_rows[1]) # 第二行字符串写入。
f.write('\n')
f.write(data_in_rows[2]) # 第三行字符串写入。
f.write('\n')
f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
用csv工具逐行写入
print('\n\n一、b. csv 工具“原始”逐行写入')
f = open(filename, 'w') # 创建文件。
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow(data_in_rows[0].split(','))
writer.writerow(data_in_rows[1].split(','))
writer.writerow(data_in_rows[2].split(','))
f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
效果图

后续内容敬请期待……
待写入字符串处理
ata_in_rows = s.strip().split('\n') # 去除前后空白并以换行符('\n')拆分待写入字符串为列表(以每条数据记录,即每行为列表元素)。
filename = r'../001/demo_csv.txt' # 要创建的文件。
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow(data_in_rows[0].split(','))
writer.writerow(data_in_rows[1].split(','))
writer.writerow(data_in_rows[2].split(','))
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
with open() 方式写入截屏图片

对文件的操作,本人建议都使用此种方法。不但语法清楚明了,且“代码块”优雅漂亮,还不用“心心念念”去记挂“文件关闭”,如有遗漏,就只得一个文件空壳。
with + for
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
for i in data_in_rows:
writer.writerow(i.strip().split(',')) # 循环写入。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
代码运行失败效果

这,怎么回事?🥴
失败!怎么会?print( ) 打印处理后的待遍历循环字符串列表元素,没毛病。这?继续查原因……
结果,我忽略了 csv.writer().writerow(list) 的参数是列表的“约定”——一行数据(以每个字段为元素的列表),她“自动”把“整行数据”字符串按单个字符列表给“处理”了。
修改 csv.writer().writerow() 参数为列表 (i.strip() .split(’,’),分割一行记录数据字符串元素为列表)
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
for i in data_in_rows:
writer.writerow(i.strip().split(',')) # 循环写入。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
代码正常运行效果

成了!!!“代码 bug 真是无处不在啊!防不胜防。😭😭”
with + while 常规写法
报错了!! Why?
File "/storage/emulated/0/qpython/csv_demo.py", line 120
while n < len(data_in_rows):
IndentationError: unexpected indent
报错截屏图片


writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 常规写法一", 'f_blue'))
n = 0
while n < len(data_in_rows):
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
仔细查探,原来又是缩进惹的祸😭😭。bug !!真是难防。🧐🧐
修改代码
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 常规写法一", 'f_blue'))
n = 0
while n < len(data_in_rows):
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 常规写法二",'f_blue'))
n = 0
while True:
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
if n == len(data_in_rows):
with + while “另类”写法
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 另类写法", 'f_blue'))
n = 0
while data_in_rows[n]:
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
if n == len(data_in_rows): break # 写完列表最后一个字符串元素,退出循环。
while 运行效果截图

OK !! 成功,三段 with + while 代码块,功用“等同”,都可以成功写入数据。
常见字符 bool 值截屏图

由试炼代码可见, while 成功循环的条件,只要是 True 就好,各人可以根据喜好设定。
本人更爱for ,感觉她“娇小玲珑”,还有人说她效率更高。
with open(filename_num, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow([f"行序号", "数据"]) # 写入表头。
for i in range(5000): writer.writerow([f"第{i+1:>5}行", f"我是第{i+1}行数据"]) # 循环写入。
#cat(filename_num) # 调用函数查看文件(文件行数太多,如果要想列印内容,去除行首#即可)。
com = system(f'ls -l {filename_num}') # 只显示文件信息,不显示内容。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")

(文件行数太多,我们就只显示文件信息,不显示内容。
文本编辑器打开

五千条记录数据的csv文件,也是一个for秒完。😄😄
读取csv文件
with open(filename) as f:
csv_str = csv.reader(f)
for row in csv_str:
print(','.join(row))
读取示例短小数据
print(f"\n\n{' pandas模块框架优雅读取csv文件 '.center(40, '~')}\n\n{pd.read_csv(filename)}")

读取示例5k“大”数据
print(f"\n\n{' pandas读取5k条记录数据csv文件,一样优雅 '.center(36, '~')}\n\n{pd.read_csv(filename_num)}")

若不想让别人直接用“文本编辑器”看到您的数据详情,可以序列化csv文件字符串,自己使用时还原就好。😄😄可以用python“私有”的pickle库,也可以用json。前者“私有”,“听说”只可以用打包的python版本还原,且是二进制操作,创建文件要用“wb”模式;后者“通用”,可以广泛用于网络“数据交换”,因其是“大家”共同的“约定”模式。
filename = '../001/pickle_demo_csv.txt'
pickle.dump(csv_str, open(filename, 'wb'))
cat(filename) # 调用函数查看文件。


filename = '../001/json_demo_csv.txt'
json.dump(csv_str, open(filename, 'w')) # 写入序列化字符串到磁盘文件。
cat(filename) # 调用函数查看文件。


逗号分隔值 (CSV) 文件包含以纯文本形式列出的表中的数据,例如电子邮件联系方式。虽然 CSV 文件可以用很多程序打开,比如文本编辑器,但是它们包含的数据最好使用电子表格程序来查看,比如Microsoft Excel、OpenOffice Calc或Google Sheets。
应用,在程序之间转移表格数据。 用法,CSV 是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。最广泛的应用是在程序之间转移表格数据,而这些程序本身是在不兼容的格式上进行操作的 (往往是私有的和/或无规范的格式)。因为大量程序都支持某种 CSV 变体,至少是作为一种可选择的输入或输出格式。 例如,一个用户可能需要交换信息,从一个以私有格式存储数据的数据库程序,到一个数据格式完全不同的电子表格。最可能的情况是,该数据库程序可以导出数据为“CSV”,然后被导出的 CSV 文件可以被电子表格程序导入。 “CSV” 并不是一种单一的、定义明确的格式 (尽管RFC4180有一个被通常使用的定义)。因此在实践中,术语 “CSV” 泛指具有以下特征的任何文件:纯文本,使用某个字符集,比如ASCII、Unicode、EBCDIC或GB2312;由记录组成 (典型的是每行一条记录);每条记录被分隔符分隔为字段 (典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格);每条记录都有同样的字段序列。 在这些常规的约束条件下,存在着许多 CSV 变体,故 CSV文 件并不完全互通。然而,这些变异非常小,并且有许多应用程序允许用户预览文件 (这是可行的,因为它是纯文本),然后指定分隔符、转义规则等。如果一个特定CSV文件的变异过大,超出了特定接收程序的支持范围,那么可行的做法往往是人工检查并编辑文件,或通过简单的程序来修复问题。因此在实践中,CSV文件还是非常方便的。 规则,开头是不留空,以行为单位。可含或不含列名,含列名则居文件第一行。一行数据不跨行,无空行。以半角逗号(即,)作分隔符,列为空也要表达其存在。列内容如存在半角逗号(即,)则用半角双引号(即"")将该字段值包含起来。列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。文件读写时引号,逗号操作规则互逆。内码格式不限,可为ASCII、Unicode或者其他。不支持特殊字符。
本练习完整源码
#!/sur/bin/nve python
# coding: utf-8
'''
filename = 'csv_demo.py'
author = '梦幻精灵_cq'
time = '2022-06-25'
'''
from time import sleep # 加载time模块暂停方法。
import csv # 载入python 内置模块。
from os import system # 加载Linux命令容器,方便用代码执行Linux命令。
from random import choice # 加载随机数模块随机选择方法。
import pickle # 加载python“私有”二进制序列化对象到字符串,方便写入磁盘文档存储。
import json # 加载json二进制序列化对象到字符串,方便写入磁盘文档存储。
from python_color import color # 加载自制色彩控制打印工具模块。
import color_tip # 加载“七彩提示字符串展示”工具
s = ' 正在加载Pandas…… ' # pandas 加载太慢,放了个“七彩提示”,所以“违规”后移了。😄
color_tip.show_tip(s, 6, 55) # 工具展示提示字符串。
import pandas as pd # 加载pandas,用其DataFrame框架展示csv数据,是很好的选择。
blank = '' # 设置空白字符变量,方便字符串插值格式化用其排版。
s = '''
昵称,性别,现居地,是否单身,爱好
梦幻精灵_cq,男,重庆巴南,否,Python
多儿,男,多邻国,是,English
'''
data_in_rows = s.strip().split('\n') # 去除前后空白并以换行符('\n')拆分待写入字符串为列表(以每条数据记录,即每行为列表元素)。
filename = r'../001/demo_csv.txt' # 要创建的文件。
def cat(filename):
''' 文件查看,在 python 环境中没有关键字“cat”,所以本函数直接用 Linux 文件查看命令 cat 命名。 '''
print(f"\n创建的 csv 文件 “{filename}” 信息及内容:\n")
system(f'ls -l {filename}')
print(color(1, 'f_green')) # 色彩控制起。
system(f'cat {filename}')
print(color(0)) # 色彩控制止。
# 一、
print('\n\n一、a. “原始” open(filename,"w")逐行写入')
print('直接字符串写入:')
f = open(filename, 'w') # 创建文件。
f.write('昵称,性别,现居地,是否单身,爱好')
f.write('\n')
f.write('梦幻精灵_cq,男,重庆巴南,否,Python')
f.write('\n')
f.write('多儿,男,多邻国,是,English')
f.write('\n')
f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
print('字符串处理数据写入:')
f = open(filename, 'w') # 创建文件。
f.write(data_in_rows[0]) # 第一行字符串写入。
f.write('\n')
f.write(data_in_rows[1]) # 第二行字符串写入。
f.write('\n')
f.write(data_in_rows[2]) # 第三行字符串写入。
f.write('\n')
f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
print('\n\n一、b. csv 工具“原始”逐行写入')
f = open(filename, 'w') # 创建文件。
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow(data_in_rows[0].split(','))
writer.writerow(data_in_rows[1].split(','))
writer.writerow(data_in_rows[2].split(','))
f.close() # 关闭文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
# 二、
print(f'\n\n二、使用 with 文件句柄\n{blank:>4}f.close() 的工作,她给“大包大揽”。您只管放手去做,有她给善后。')
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow(data_in_rows[0].split(','))
writer.writerow(data_in_rows[1].split(','))
writer.writerow(data_in_rows[2].split(','))
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
# 三、
print('\n\n三、用 with + 循环(while、for 据个人喜好选用)\n{blank:>4}代码还会精炼—— 1~无穷大 (∞) 的数据条数的写入,都是那“点点”代码。真是应了那句“任你千变万化,我自巍然不动”。😎😎')
print(color('\n\n with + for 循环:', 'f_green'))
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
for i in data_in_rows:
writer.writerow(i.strip().split(',')) # 循环写入。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
print(color('\n\n with + while 循环:', 'f_green'))
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 常规写法一", 'f_blue'))
n = 0
while n < len(data_in_rows):
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 常规写法二",'f_blue'))
n = 0
while True:
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
if n == len(data_in_rows): break # 写完列表最后一个字符串元素,退出循环。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
with open(filename, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
print(color(f"\n\n while 另类写法", 'f_blue'))
n = 0
while data_in_rows[n]:
writer.writerow(data_in_rows[n].strip().split(',')) # 循环写入。
n += 1 # 更新列表下标(写入下一行)。
if n == len(data_in_rows): break # 写完列表最后一个字符串元素,退出循环。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
filename_num = "../001/csv_5knum.db"
for_str = '''
for i in range(5000):
writer.writerow([f"第{i+1:>5}行", f"我是第{i+1}行数据"]) # 循环写入。
'''
for_join = ' '.join(for_str.strip().split('\n'))
for i in range(9): for_join = for_join.replace(' ', ' ') # 去除字符串多余半角空格' '。
print(color('\n\n让我们一起见证 with + for 循环的“强悍”:', 'f_green'))
print(f" 写入5k条记录数据,也还是那行for循环语句。".center(30, '~'))
print(f"{color(for_str, 'f_green')}\n(for下只有一条语句,可以写成一行):\n{color(for_join, 'f_green')}\n\n")
with open(filename_num, 'w') as f:
writer = csv.writer(f) # 创建 csv.writer 实例。
writer.writerow([f"行序号", "数据"]) # 写入表头。
for i in range(5000): writer.writerow([f"第{i+1:>5}行", f"我是第{i+1}行数据"]) # 循环写入。
#cat(filename_num) # 调用函数查看文件(文件行数太多,如果要想列印内容,去除行首#即可)。
com = system(f'ls -l {filename_num}') # 只显示文件信息,不显示内容。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
# 一、csv文件读取,除了(),还可以——
print(f"\n\n{' 纯文本编辑器读取csv文件 '.center(40, '~')}\n")
print(f"{' (Linux下cat命令打印那个样子,在此不再演示) '.center(34, '~')}\n")
print(f"\n\n{' csv模块工具读取csv文件 '.center(42, '~')}\n")
with open(filename) as f:
csv_str = csv.reader(f)
for row in csv_str:
print(','.join(row))
print(f"\n\n{' pandas模块框架优雅读取csv文件 '.center(40, '~')}\n\n{pd.read_csv(filename)}")
print(f"\n\n{' pandas读取5k条记录数据csv文件,一样优雅 '.center(36, '~')}\n\n{pd.read_csv(filename_num)}")
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
print(f"\n\n{' 序列化对象到文件 '.center(40, '~')}\n")
with open(filename) as f:
csv_str = f.read()
print(csv_str)
print(f"\n\n{' 一、pickle序列化 '.center(45, '~')}\n")
filename = '../001/pickle_demo_csv.txt'
pickle.dump(csv_str, open(filename, 'wb'))
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
print(f"\n\n{' 二、json序列化 '.center(45, '~')}\n")
filename = '../001/json_demo_csv.txt'
json.dump(csv_str, open(filename, 'w')) # 写入序列化字符串到磁盘文件。
cat(filename) # 调用函数查看文件。
input(f"\n\n{color(' wait ... ','f_gray').center(59, '~')}")
参阅学习博文: