在数据分析中,我们通常用pandas的 read_csv方法来读取系统中的文件,但理解这背后的原理也是非常重要的,而且幸运的是,这很简单。
Python与文件、操作系统交互
文件读取
python使用open方法接受一个路径(绝对或相对路径都可以)来读取读取文件:
1 | path = '/Users/wittyfans/Documents/data/all_girls.csv' # :) |
默认打开是以 r 模式打开的,即只读。
我们可以用推导式来读取文件中的行:
1 | lines = [x.rstrip() for x in open(path)] |
当你使用open方法创建一个文件的时候,一定要关掉这个文件:
1 | f.close() |
python也考虑到了一些人可能记性不好,所以建议你使用这种方式跟文件交互:
1 | with open(path) as f: |
with 语句会自动关闭文件。
在使用open语句的是,有一点要小心,如果当前文件夹內有一个a.txt的文件,如果你不小心使用了 f = open('./a.txt','w') 语句,那么python会立即创建一个a.txt文件,并替换掉当前的(小心⚠️)。
假设当前文件夹中有一个ftext.txt文件,如果我运行下面的代码,则可以正常显示文件中的内容: 1
2
3with open("./ftest.txt") as f:
lines = [line for line in f]
print(lines)
如果我这样写:
1 | with open("./ftest.txt",'w') as f: |
则会报错:UnsupportedOperation: not readable,因为文件依据被覆盖。 文件模式还有一个 x,它也会在path指定的路径中创建文件,不过如果路径中已经有了文件,则会创建失败。
如果你想在读取文件的时候,了解当前读取到了哪一行,或者根据行数去做控制,可以使用 f.tell() 函数。
写文件
使用文件对象的 write 或者 writelines 方法即可向文件执行写操操作:
1 | with open('tmp.txt','w') as handle: |
Bytes和Unicode类型
计算机最早的编码类型是ASCII,能存一个字节的信息,对与英文刚好够用,但是如果对于汉字,最少需要两个字节才能存下来,所以后面为了统一,就制定了Unicode。因为用两个字节去存本来一个字节就可以存下来的东西,unicode会有些浪费,于是就出现了utf-8,它把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节,这样在网络上传输的时候,可以节省很多带宽。
这些编码都是可以相互转化的,在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节,如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。
python中的字节:
1 | x = b'ABC'# 字节类型的数据,只占用一个字节 |
unicode类型的数据(str),可以转化成字节类型表示的数据,通过encode方法:
1 | 'ABC'.encode('ascii') # unicode类型的str,转化成ascii编码类型的数据,转化后占用1个字节 |
在python中,如果你想要读取10个字符:
1 | with open(path) as f: |
这样会从文件中读取10个字符,也就是UTF-8格式下的10个字符。
如果你以 rb 模式打开:
1 | with open(path,'rb') as f: |
则python会读取10个字节,如果是同一份数据,则读取10个字节的这种方式会少一些数据。
对于file的seek方法要注意,如果你使用的时候出错,会导致后面的读取也出错。