由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。s
    Stream(流)
    Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去
    同步IO
    异步IO
    同步和异步的区别就在于是否等待IO执行的结果
    异步通知你的方法: 回调模式 轮询模式
    异步IO的复杂度远远高于同步IO。
    操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。我们后面会详细讨论Python的IO编程接口。
    注意,本章的IO编程都是同步模式,异步IO由于复杂度太高,后续涉及到服务器端程序开发时我们再讨论。
    文件读写
    读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
    Python内置了读写文件的函数,用法和C是兼容的
    f=open(‘C:\Users\LCG\Desktop\PY\io\test.txt’,’r’)
    Python引入了with语句来自动帮我们调用close()方法:
    with open(‘/path/to/file’, ‘r’) as f:
    print f.read()

    1. 这和前面的try … finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
    2. 可以反复调用read(size)方法,每次最多读取size个字节的内容
    3. 调用readline()可以每次读取一行内容
    4. 调用readlines()一次读取所有内容并按行返回list

    for line in f.readlines():
    print(line.strip()) # 把末尾的’\n’删掉
    file-like Object
    像open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object.
    除了file外,还可以是内存的字节流,网络流,自定义流等等
    StringIO就是在内存中创建的file-like Object,常用作临时缓冲。
    Python还提供了一个codecs模块帮我们在读文件时自动转换编码,直接读出unicode
    import codecs
    with codecs.open(‘/Users/michael/gbk.txt’, ‘r’, ‘gbk’) as f:
    f.read() # u’\u6d4b\u8bd5’
    with open(‘/Users/michael/test.txt’, ‘w’) as f:
    f.write(‘Hello, world!’)
    使用with语句操作文件IO是个好习惯。
    操作文件和目录
    Python内置的os模块也可以直接调用操作系统提供的接口函数。
    操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中
    文件目录的创建删除与重命名
    os.path.join()函数 把两个路径合成一个
    os.path.split()函数,可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名
    os.path.splitext()可以直接让你得到文件扩展名
    这些合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操作。
    os.rename(‘test.txt’, ‘test.py’)
    os.remove(‘test.py’)
    但是不能复制
    幸运的是shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充。
    os.listdir(‘.’) 列出当前目录下文件
    os.path.isdir(x) 该目录是不是目录
    os.path.isfile(x) 该目录是不是文件
    [x for x in os.listdir(‘.’) if os.path.isfile(x) and os.path.splitext(x)[1]==’.py’]
    要列出所有后缀名为.py文件,也只需一行代码
    print [x for x in os.listdir(‘.’) if os.path.split(x)[1].find(‘1’) >= 0]
    print [x for x in os.listdir(‘.’) if x.find(‘1’) >= 0]
    两个效果一样的?
    找出当前目录下文件名或后缀名里面有1的文件或文件夹,不可对下一级目录进行操作。
    pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
    序列化
    我们把变量从内存中变成可存储或传输的过程称之为序列化
    在Python中叫pickling
    反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
    cPickle和pickle
    cStringIO和StringIO
    pickle.dumps()方法把任意对象序列化成一个str,然后,就可以把这个str写入文件。
    用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object
    当我们要把对象从磁盘读到内存时,可以先把内容读到一个str,然后用pickle.loads()方法反序列化出对象
    也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象
    Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
    JSON
    如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON。
    因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。
    JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
    JSON表示的对象就是标准的JavaScript语言的对象
    反序列化得到的所有字符串对象默认都是unicode而不是str
    由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str或unicode与JSON的字符串之间转换

    1. 原来格式为表格(table),转换较复杂,未转换,需要手动复制一下
    2. {"cells":[{"verticalAlign":"middle","wrap":true,"value":"JSON类型"},{"verticalAlign":"middle","wrap":true,"value":"Python类型"},{"verticalAlign":"middle","wrap":true,"value":"{}"},{"verticalAlign":"middle","wrap":true,"value":"dict"},{"verticalAlign":"middle","wrap":true,"value":"[]"},{"verticalAlign":"middle","wrap":true,"value":"list"},{"verticalAlign":"middle","wrap":true,"value":"\"string\""},{"verticalAlign":"middle","wrap":true,"value":"'str'或u'unicode'"},{"verticalAlign":"middle","wrap":true,"value":"1234.56"},{"verticalAlign":"middle","wrap":true,"value":"int或float"},{"verticalAlign":"middle","wrap":true,"value":"true/false"},{"verticalAlign":"middle","wrap":true,"value":"True/False"},{"verticalAlign":"middle","wrap":true,"value":"null"},{"verticalAlign":"middle","wrap":true,"value":"None"}],"heights":[40,40,40,40,40,40,40],"widths":[70,70]}

    通常class的实例都有一个dict属性,它就是一个dict,用来存储实例变量
    print(json.dumps(s, default=lambda obj: obj.dict))

    • Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。
    • json模块的dumps()和loads()函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。
    • 但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。

    序列化应该是将对象的状态信息转换为可以存储或传输的形式的过程,
    而不是变量存储到磁盘的过程. 存储到磁盘的过程应该是持久化.
    序列化不一定要存储。