python常用模块学习:csv实例教程
python3读取csv文件所提供的简便方法
- 常用方法
方法 | 含义 |
reader() | 按行读取,返回值是一个迭代对象 |
DictReader() | 读取结果生成一个dict |
csv.writer() | 以元组的方式写入 |
csv.DictWriter() | 以字典的形式写入 |
- 使用实例
- 读取csv文件,并将结果以字典类型返回
- 通过csv.DictReader()方法生成的字典内会存在换行符,但此换行符对文件的读取与使用并没有影响。
- with open as ...方法的好处:每次对文件进行操作后,会主动关闭文件操作空间,“a”是指打开文件存入的变量。

- 读取csv文件,并将结果以列表的形式返回
- 什么是迭代器?
- 当某个对象可以使用for循环将所有的值都遍历出来的时候,那么此对象就可以作为迭代器。
- 可迭代对象本质是什么?
- 可迭代对象进行迭代的过程中,作为每次帮助我们进行数据迭代的对象,被称为迭代器。
import csv def read_csv_demo1(): with open("china_smoking.csv", "r") as fp: # reader是一个迭代器 reader = csv.reader(fp) # 如果不需要输出标题,可以next()方法,把迭代器往下挪 next(reader) # 这样通过下标的方式去获取 for x in reader: Location = x[1] smoking_yes_cancer_yes = x[2] print({"Location":Location,"smoking_yes_cancer_yes":smoking_yes_cancer_yes}) read_csv_demo1()
- 以元组的方式将内容写入csv文件
- newline=""参数的作用是防止写入的csv文件每一行后都多一行空行;
- writer.writerow与writer.writerows的区别:
- writer.writerow:单行写入,将一个列表全部写入csv的同一行;
- writer.writerows:多行写入,将一个二维列表的每一个列表写为一行;
- writer.writerow常用来写入表头,writer.writerows常用来写入每行数据内容;
import csv def writer_csv_demo1(): headers = ["name","age","height"] values = [ ("小王",18,178), ("小张",20,180), ("小李",17,166) ] with open("classroom.csv","w",encoding="utf-8",newline="") as fp: writer = csv.writer(fp) writer.writerow(headers) writer.writerows(values) writer_csv_demo1()
- 以字典的方式将内容写入csv文件
def writer_csv_demo2(): headers = ["name", "age", "height"] values = [ {"name":"小王","age":18,"height":178}, {"name":"小王","age":18,"height":178}, {"name":"小王","age":18,"height":178} ] with open("classromm2.csv","w", encoding="utf-8",newline="") as fp: # 使用csv.DictWriter()方法,需传入两个个参数,第一个为对象,第二个为文件的title writer = csv.DictWriter(fp,headers) # 使用此方法,写入表头 writer.writeheader() writer.writerows(values) writer_csv_demo2()
- I/O操作
- 概念
- python文件读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
- 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘。
- 读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)
- 常见操作类型
参数 | 含义 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。 |
w | 打开一个文件只用于写入。若文件存在则将其覆盖,若文件不存在,则创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
- 常规方式
- 打开文件
f = open( '/Users/michael/test.txt', 'r' )
- r 表示读取文件,我们就成功地打开了一个文件
- 若如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在,错误情况如下:
f=open('/Users/michael/notfound.txt', 'r') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/notfound.txt'
- 读取文件
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:
f.read() 'Hello, world!'
- 关闭文件
最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:
f.close()
- 整体操作方法
由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try … finally来实现:
try: f = open('/path/to/file', 'r') print(f.read()) finally: if f: f.close()
- 推荐方式
- 读取方式
- 每次如果都按照如上最终方案去写的话,实在太繁琐。
- Python引入了with语句来自动帮我们调用close()方法。
方法 | 含义 |
f.read() | 读取全部文件内容 |
f.read(size) | 每次读取size个字节内容 |
f.readline() | 每次读取一行的内容 |
f.readlines() | 读取全部内容,但结果返回list,每行内容是一个元素 |
with open( '/path/to/file', 'r' ) as f: print( f.read() ) # 这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法
如果遇到超大文件,需要注意:
- 调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了。
- 要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。例如,read(1024) 每次读取1024个字节的数据内容
- 调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
- 如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便:
for line in f.readlines(): print( line.strip() ) # 读取文件之后,文字末尾会出现'\n' # strip() 函数中可以把目标内容line里面所有的空格,空行等都删除掉,只剩余文字内容
- 跳过第一行内容(字段名)
with open(file_path, 'r', encoding='utf-8-sig') as f: next(f) # 最终读取到的内容,直接跳过第一行了 all_line_list = f.readlines()
- 写入内容---open函数
open函数使用注意地方:
- 你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。
- 当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
- 只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险。
f = open('/Users/michael/test.txt', 'w') f.write('Hello, world!') f.close()
- 写入内容---with open函数
要写入特定编码的文本文件,请给open()函数传入encoding参数,将字符串自动转换成指定编码字符编码
写入文件时需要添加encoding='utf-8'参数,这样可以防止写入中文不乱码
with open('/Users/michael/test.txt', 'w',encoding='utf-8') as f: f.write('Hello, world!')
- 将文件内容写入csv文件
with open("test.csv", "a", newline="") as csvfile: rows = ("商品名称", "商品价格", "商品链接") writer = csv.writer(csvfile) writer.writerow(rows)
- 读取txt文件内容
读取文件内每一行的内容,然后将每一行的内容通过split获取特定的结果
with open(path,"r",encoding="utf-8") as number: lines = number.readlines() j = 0 for line in lines: try: temp = line.split(name) t = temp[1].split(':') ack1 = t[1].split(",") ack2 = t[2].split(",") ack3 = t[3].split("}") except: continue step.append(j) j = j + 1 ack_1.append(int(ack1[0])) ack_2.append(int(ack2[0])) ack_3.append(int(ack3[0]))
- 打开非utf-8编码的文件
要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:
with open('/Users/michael/gbk.txt', 'r', encoding='gbk') as f: f.read()
- 遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。
- open()函数还接收一个errors参数,errors=‘ignore’ 表示遇到编码错误的时候直接忽略。
with open('/Users/michael/gbk.txt', 'r', encoding='gbk',errors='ignore') as f: f.read()
前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频等等,用’rb’模式打开文件即可:
with open('/Users/michael/test.jpg', 'rb') as f: f.read() # b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' 十六进制表示的字节
- 全局变量
- 概念
Python全局变量是指其有效范围为整个程序空间。在程序的任何一个地方都可以访问这个变量,不管是在函数内部还是函数外部。
- 全局变量的有效作用范围
- 函数后定义变量
def myFunction(): print('Inside myFunction(): ',myVar) myFunction() myVar = 'hello python - global' print('Outside myFunction(): ',myVar) 运行结果: 运行将报告错误:NameError: name 'myVar' is not defined
- 运行以上代码会报错,因为在函数调用的过程中,其变量myVar还没有声明。
- 在函数外定义的变量,只会在定义后的代码内才能正常生效。
- 函数内更改变量
myVar = 'hello python - global' def myFunction(): myVar = 'hello python - local' print('Inside myFunction(): ',myVar) myFunction() print('Outside myFunction(): ',myVar) 运行结果: Inside myFunction(): hello python - local Outside myFunction(): hello python - global
- 当在一个函数内修改与全局变量相同的局部变量时,python会认为这是一个"破坏性"的行为,即便外面存在一个同名的全局变量,若你没有明确告诉python你要访问全局变量,安全起见,python会认为你只想为局部变量赋值,它会自动创建一个局部变量以供使用。
- 若想在一个函数内部想看一个变量而在函数内部又没有对这个变量进行显示声明,然后又恰好存在一个同名的全局变量时,python会缺省地认为你是想看这个全局变量。
- global关键字
#若想在一个函数内部对全局变量赋值更新,可以用global关键字明确地告知python myVar = 'hello python - global' def myFunction(): global myVar myVar = 'hello python - I changed you inside myFunction' print('Inside myFunction(): ',myVar) myFunction() print('Outside myFunction(): ',myVar) 运行结果: Inside myFunction(): hello python - I changed you inside myFunction Outside myFunction(): hello python - I changed you inside myFunction
- 跨模块的情况
在python中,一个源代码文件可以看作是一个模块(module)。在一个模块中声明了一个全局变量后,只要把前一个模块import后,就可以在另一个模块中查看前一个模块的全局变量了。
myVar = 'hello python - global, in python_global_1 module' def myFunction1(): global myVar myVar = 'hello python - I changed you inside myFunction' print('Inside myFunction(): ',myVar)
from python_global_1 import * def myFunction(): print('Inside myFunction(): ',myVar) myFunction() print('Outside myFunction(): ',myVar) 运行结果: Inside myFunction(): hello python - global, in python_global_1 module Outside myFunction(): hello python - global, in python_global_1 module