1.文件读写
>>>f = open('/Users/michael/test.txt', 'r') >>> f.read() 'Hello, world!' >>> 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()方法: with open('/path/to/file', 'r') as f: print f.read()
调用read()
会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)
方法,每次最多读取size个字节的内容。另外,调用readline()
可以每次读取一行内容,调用readlines()
一次读取所有内容并按行返回list
。因此,要根据需要决定怎么调用。
如果文件很小,read()
一次性读取最方便;如果不能确定文件大小,反复调用read(size)
比较保险;如果是配置文件,调用readlines()
最方便:
for line in f.readlines(): print(line.strip()) # 把末尾的'\n'删掉
前面讲的默认都是读取文本文件,并且是ASCII编码的文本文件。要读取二进制文件,比如图片、视频等等,用'rb'
模式打开文件即可:
>>> f = open('/Users/michael/test.jpg', 'rb') >>> f.read() '\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
要读取非ASCII编码的文本文件,就必须以二进制模式打开,再解码。比如GBK编码的文件:
>>> f = open('/Users/michael/gbk.txt', 'rb') >>> u = f.read().decode('gbk') >>> u u'\u6d4b\u8bd5' >>> print u 测试
写文件和读文件是一样的,唯一区别是调用open()
函数时,传入标识符'w'
或者'wb'
表示写文本文件或写二进制文件。
你可以反复调用write()
来写入文件,但是务必要调用f.close()
来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()
方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()
的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with
语句来得保险:
with open('/Users/michael/test.txt', 'w') as f: f.write('Hello, world!')
2.操作文件和目录
>>> import os >>> os.name # 操作系统名字 'posix' >>> os.uname() #详细系统信息 ('Darwin', 'iMac.local', '13.3.0', 'Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64', 'x86_64') >>> os.environ #操作系统环境变量,dict类型 {'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'TERM_PROGRAM_VERSION': '326', 'LOGNAME': 'michael', 'USER': 'michael', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin', ...} >>> os.getenv('PATH') #获取某个环境变量的值 '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin'
# 查看当前目录的绝对路径: >>> os.path.abspath('.') '/Users/michael' # 在某个目录下创建一个新目录, # 首先把新目录的完整路径表示出来: >>> os.path.join('/Users/michael', 'testdir') '/Users/michael/testdir' # 然后创建一个目录: >>> os.mkdir('/Users/michael/testdir') # 删掉一个目录: >>> os.rmdir('/Users/michael/testdir') #通过os.path.split()函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名: >>> os.path.split('/Users/michael/testdir/file.txt') ('/Users/michael/testdir', 'file.txt') # os.path.splitext()可以直接让你得到文件扩展名 >>> os.path.splitext('/path/to/file.txt') ('/path/to/file', '.txt') # 对文件重命名: >>> os.rename('test.txt', 'test.py') # 删掉文件: >>> os.remove('test.py')
复制文件的函数居然在os
模块中不存在!原因是复制文件并非由操作系统提供的系统调用
幸运的是shutil
模块提供了copyfile()
的函数,你还可以在shutil
模块中找到很多实用函数,它们可以看做是os
模块的补充
>>>import shutil >>>shutil.copyfile('C:\\Users\\konglingxi\\Desktop\\test.txt','C:\\Users\\konglingxi\\Desktop\\t.txt')
小应用:
##列出当前目录下的所有目录 >>> [x for x in os.listdir('.') if os.path.isdir(x)] ['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Adlm', 'Applications', 'Desktop', ...] ##列出所有的.py文件 >>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py'] ['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']
3.序列化
变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思;把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling
pickle模块
## 变量操作 >>>import pickle >>>d1 = {'name':'klc','age':18} >>>dumps = pickle.dumps(d1) >>>dumps "(dp0\nS'age'\np1\nI18\nsS'name'\np2\nS'klc'\np3\ns." >>>loads = pickle.loads(dumps) >>>loads {'age': 18, 'name': 'klc'} ## file-like object操作 >>>f = open('C:\\Users\\konglingxi\\Desktop\\t.txt','w+') >>>pickle.dump(d1,f) >>>f.close() >>>f = open('C:\\Users\\konglingxi\\Desktop\\t.txt','r+') >>>d2 = pickle.load(f) >>>d2 {'age': 18, 'name': 'klc'}
json模块
## 变量操作 >>>import json >>>d1 = {'name':'klc','age':18} >>>dumps = json.dumps(d1) >>>dumps "(dp0\nS'age'\np1\nI18\nsS'name'\np2\nS'klc'\np3\ns." >>>loads = json.loads(dumps) >>>loads {'age': 18, 'name': 'klc'} ## file-like object操作 >>>f = open('C:\\Users\\konglingxi\\Desktop\\t.txt','w+') >>>json.dump(d1,f) >>>f.close() >>>f = open('C:\\Users\\konglingxi\\Desktop\\t.txt','r+') >>>d2 = json.load(f) >>>d2 {'age': 18, 'name': 'klc'}