[Pyhon]IO编程

来源:互联网 发布:https的默认端口是 编辑:程序博客网 时间:2024/06/11 15:36

Python内置了读写文件的函数,用法和C是兼容的。

文件读写

file-like Object

open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object
除了file外,还可以是内存的字节流,网络流,自定义流等等。
file-like Object不要求从特定类继承,只要写个read()方法就行。

StringIO就是在内存中创建的file-like Object,常用作临时缓冲。

操作 用法、例子 参数、返回值 打开文件 open('fileName','openMode',encoding='gbk')

f = open('/test.txt', 'rb') utf-8格式的文件不需要传入encoding
文件不存在,抛出IOError错误
文件存在,返回file-like Object
r/rb 读出文本文件/二进制文件
w/wb 写入文本文件/二进制文件 读文件 f.read() 一次性读取所有内容
f.read(size) 每次最多读取size个字节的内容
f.readlines()每次读取一行内容
readlines()一次读取所有内容并按行返回list 返回读到的数据 写文件 f.write('hello')

注意:

  • 遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError。
    open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理
    最简单的方式是直接忽略:
    f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
  • 因为读写都可能抛出IOError错误,为了出错之后还能及时关闭f.close
    1.try ... finally if f: f.close()
    2.with open('/file','r') as f : with可以自动帮我们调用close()
  • 不要忘记关闭文件,因为有一部分数据是在缓冲区里,不执行close()关闭文件的话,可能会导致文件数据丢失。

内存读写

StringIOBytesIO是在内存中操作strbytes的方法,使得和读写文件具有一致的接口。

StringIO读写str

from io import StringIOf = StringIO(Hello!)while True:    s = f.readline()    if s == '':        break    print(s.strip())f.write('hello') #返回写入的字符数print(f.getvalue()) #getvalue获取写入后的str

BytesIO读写二进制数据

>>> from io import BytesIO>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')>>> f.read()>>> f.write('中文'.encode('utf-8'))6>>> f.getvalue()b'\xe4\xb8\xad\xe6\x96\x87'

系统

Python内置的os模块直接调用操作系统提供的接口函数,封装了操作系统的目录和文件操作。

>>> import os>>> os.name # 操作系统类型'nt' # nt,就是Windows系统; posix,说明系统是Linux、Unix或Mac OS X。>>> os.uname() # 获得详细的系统信息。uname()函数在Windows上不提供posix.uname_result(sysname='Darwin', nodename='MichaelMacPro.local', release='14.3.0', version='Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64', machine='x86_64')

环境变量

直接可以在交互式命令行执行查看

>>> os.environ  # 所有环境变量environ({'...'})>>> os.environ.get('PATH') # 获取某个环境变量:'/usr/bin:/bin:/usr/sbin'>>> os.environ.get('x', 'default') # 如果x不存在,返回default'default'

操作文件和目录

# 查看当前目录的绝对路径>>> os.path.abspath('.')'/Users/test'# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来>>> os.path.join('/Users/test', 'testdir')'/Users/test/testdir'# 把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名>>> os.path.split('/Users/test/testdir/file.txt')('/Users/test/testdir', 'file.txt')# 获得文件扩展名>>> os.path.splitext('/path/to/file.txt')('/path/to/file', '.txt')# 创建一个目录>>> os.mkdir('/Users/test/testdir')# 删掉一个目录>>> os.rmdir('/Users/test/testdir')# 对文件重命名>>> os.rename('test.txt', 'test.py')# 删掉文件>>> os.remove('test.py')# 是不是目录文件:返回Ture/False>>> os.path.isdir(x)  # 是不是文件>>> os.path.isfile(x)# 列出当前目录下的所有目录>>> [x for x in os.listdir('.') if os.path.isdir(x)]['.lein', '.local', 'Desktop', ...]# 列出当前目录下,所有的.py文件>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']['apis.py', 'wsgiapp.py']

注意:

  • 为了兼容不同操作系统的路径分隔符。linux/Unix/Mac ‘/’; Win ‘\’
    不要直接拼接或者拆分字符串,一定要使用下列函数
    字符串拼接:os.path.join()
    字符串拆分:os.path.split()
  • 操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中
  • shutil模块提供了copyfile()的函数

序列化

定义:变量从内存中变成可存储或传输的过程[pickling]
在其他语言中被称为serialization,marshalling,flattening

序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

>>> import pickle>>> d = dict(name='Bob', age=20, score=88)>>> pickle.dumps(d) # 把任意对象序列化成一个bytesb'\x80\x03}q\x00(X\x03\x00\x00\x00ageq.'>>> f = open('dump.txt', 'wb')>>> pickle.dump(d, f)  # 直接把对象序列化后写入一个file-like Object>>> f.close()>>> pickle.loads() # 先把内容读到一个bytes,然后反序列化出对象>>> f = open('dump.txt', 'rb')>>> d = pickle.load(f) # 从一个file-like Object中直接反序列化出对象>>> f.close()>>> d{'age': 20, 'score': 88, 'name': 'Bob'}

反序列化,把变量内容从序列化的对象重新读到内存里,即unpickling。

JSON

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,JSON

JSON的优点

  • JSON表示出来就是一个字符串,可以被所有语言读取
  • 可以方便地存储到磁盘或者通过网络传输
  • JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便

JSON表示的对象就是标准的JavaScript语言的对象

JSON和Python内置的数据类型对应如下

JSON类型 Python类型 {} dict [] list "string" str 1234.56 intfloat true/false True/False null None

Python内置的json模块提供了非常完善的Python对象到JSON格式的转换
由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换。

Python对象序列化

Python对象变成一个JSON:

>>> import json>>> d = dict(name='Bob', age=20, score=88)>>> json.dumps(d)  # 把Python对象变成一个JSON,返回str'{"age": 20, "score": 88, "name": "Bob"}'>>> f = open('dump.txt', 'wb')>>> json.dump(d, f)  # 把对象变成一个JSON后写入一个file-like Object>>> f.close()

JSON反序列化为Python对象:

>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'>>> json.loads(json_str) # 把JSON的字符串反序列化{'age': 20, 'score': 88, 'name': 'Bob'}>>> f = open('dump.txt', 'rb')>>> json.load(f) # 从file-like Object中读取字符串并反序列化{'age': 20, 'score': 88, 'name': 'Bob'}

class对象序列化

class对象变成一个JSON:

import jsonclass Student(object):    def __init__(self, name, age, score):        self.name = name        self.age = age        self.score = scores = Student('Bob', 20, 88)print(json.dumps(s))

直接运行会得到TypeError, Student对象不是一个可序列化为JSON的对象
因为默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象

Traceback (most recent call last):  ...TypeError: <__main__.Student object at 0x10603cc50> is not JSON serializable

dumps()可选参数让我们可以定制JSON序列化
dumps()可选参数

可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student专门写一个转换函数,再把函数传进去即可

# 方法一def student2dict(std):    return {        'name': std.name,        'age': std.age,        'score': std.score    }
>>> print(json.dumps(s, default=student2dict)) {"age": 20, "name": "Bob", "score": 88}
# 方法二# 通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。>>> print(json.dumps(s, default=lambda obj: obj.__dict__)) {"age": 20, "name": "Bob", "score": 88}

JSON反序列化为class对象:

def dict2student(d):    return Student(d['name'], d['age'], d['score'])
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'>>> print(json.loads(json_str, object_hook=dict2student)) # 打印出的是反序列化的Student实例对象<__main__.Student object at 0x10cd3c190>

注意

  • json模块的dumps()loads()函数是定义得非常好的接口的典范
    既做到了接口简单易用,又做到了充分的扩展性和灵活性
    当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则.
0 0
原创粉丝点击