zoukankan      html  css  js  c++  java
  • 五、IO编程

    input/output:输入、输出

    Stream(流):Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。(流:相当于管道)

    由于CPU和内存的速度远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。例如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,磁盘要接收这100M数据可能需要10秒,所以存在两种模式:

    1. 同步IO:CPU等着,程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行
    2. 异步IO:CPU不等待,继续执行后续代码,后续再回来接收。(较复杂)

    一、文件读写

    • 文件处理流程
    1. open()函数打开文件,得到文件句柄并赋值(不在同一路径下的需加 .py)
    2. 通过句柄对文件进行操作 (文件句柄相当于下文的 f )
    3. close()函数关闭文件
    • 文件打开模式
      • 读操作:解码默认GBK; open() 函数还可接收 errors 参数,可用  errors=ignore  忽略编码错误。
        1 r:只读,w:只写 ,a:追加
        2 f = open('文件名','权限',encoding='utf-8')    #传入需要打开的文件名并进行解码
        3 data = f.read() #查看文件
        4 print(date)
        5 f.close()   #关闭文件
         1 f = open('测试文件','r',encoding='utf-8')
         2 # date = f.read()
         3 # print(date)               #文件只打印一次,后面再打印不显示内容
         4 # print(f.readable())       #判断权限
         5 # print(f.readline())       #打印一行,没内容即不打印
         6 print(f.readlines())        #将文件内容每段以字符串的方式显示出来,并存在一个列表中
         7 f.close()
         8 
         9 输出:
        10 ['11111111111
        ', '22222222222
        ', '33333333333']
      • 写操作:直接新建空文档覆盖原来的文档

        1 f = open('测试文件','w',encoding='utf-8')
        2 f.write('1111
        ')
        3 f.writelines(['111','222']) #以列表的方式写入,内容只能是字符串
        4 f.writable()
        5 f.close()
      • 追加操作:将内容写到文件最后,不覆盖文件内容
      • r+:可读可写;w+a+x+。
        1 f = open('测试文件','r+',encoding='utf-8')
        2 f.write('内容')   #将内容覆盖到测试文件的开头,根据占用的字节进行替换
      • with...as...:可不用  close() 关闭文件
        1 #可使用with..as..:来打开或修改文件,不需要用close关闭。
        2 with open('测试文件','r',encoding='utf-8') as arc_f,/    #字符太长使用‘/‘进行换行处理
        3         open('新文件','w',encoding='utf-8') as dst_f:
      • 修改文件上的内容
        1 #查看文件内容并赋值到date上
        2 src_f = open('测试文件','r',encoding='utf-8')
        3 date = src_f.readline()
        4 src_f.close()
        5 #修改date索引位置的内容
        6 dst_f = open('测试文件','w',encoding='utf-8')
        7 dst_f.writelines(date[0])
        8 dst_f.close()
      • rb、wb、ab:可用于读取二进制文件,比如图片、视频等,不能指定编码(Windows下的换行为 ,Linux为 。 编码后再加 " newline=‘ ' ”读取文件真正换行符: )
      1. 转成二进制:字符串 -----》encode(编码)-----》》bytes
      2. 查看二进制:bytes -----》decode(解码)-----》》字符串
        1 #使用 rb 进行查看,返回二进制数
        2 f = open('test1.py','rb')
        3 date = f.read()
        4 print(date)
        5 f.close()
        6 
        7 输出:
        8 b'11111
        xe4xbdxa0xe5xa5xbd
        ' 
        1 #使用 wb 新建文件或写入内容,需进行编码
        2 f = open('test1.py','wb')
        3 date = f.write('1234
        你好'.encode('utf-8'))
        4 4# date = f.write(bytes('1234
        你好',encoding='utf-8'))
        5 f.close()
      • flush():刷新文件
      • seek():里面加数字,表示文件光标移动多少个字节(一个汉字占用三个字节,排除第一个汉字时为:文件句柄.seek(3),默认为: 文件句柄.seek(3,0) )
        • 文件句柄.seek(3,1)表示相对位置,即从上一个移到的位置接着往下移动;文件句柄.seek(-3,2)表示光标从后往前的位置。
      • read():文件句柄.read(1)表示读取文件一个位置的内容,汉字占用三个字节也用一个表示。与其它方法的表示不一样
      • truntruncate():加数字表示截取文件多少个字节的内容。需以写的方式打开,w与w+除外。
         1 #使用seek倒查文件最后一行
         2 f = open('test.txt', 'rb')
         3 for i in f:  # 使用for i in f 系统不会把所有数据读到内存中,而是需要读取时再读
         4     offs = -10  # 定义一个偏移量,因为倒查,所以为负数
         5     while True:
         6         f.seek(offs, 2)  # 
         7         data = f.readlines()  # 使用readlines(),会得到一个光标所在位置到结尾所有行的一个列表
         8         if len(data) > 1:  # 当列表大于1时,说明已取到完整的最后一行
         9             print(data[-1].decode('utf-8'))
        10             break
        11         offs *= 2  # 如果得到的列表不大于1,说明最后一行得到了一部分,就把偏移量*2,再进行循环

    二、StringIO和BytesIO

    • StringIO:在内存中读、写str,可先用一个str 初始化内容
       1 #读取StringIO内的文件
       2 from io import StringIO
       3 f = StringIO('hello
      hi
      goodbye')    
       4 while True:
       5     s = f.readline()
       6     if s == '':
       7         break
       8     print(s.strip())
       9 
      10 输出:
      11 hello
      12 hi
      13 goodbye
       1 #将字符串写入StringIO
       2 from io import StringIO
       3 f = StringIO()
       4 date = f.write('hello')
       5 f.write(' ')
       6 f.write('world!')
       7 print(date)
       8 print(f.getvalue()) #getvalue 获取写入后的字符串
       9 
      10 输出:
      11 5
      12 hello world!
    • BytesIO:在内存中读、写二进制数据
       1 #将bytes写入BytesIO
       2 from io import BytesIO
       3 f = BytesIO()
       4 date = f.write('中文'.encode('utf-8'))    #需将str经过utf-8编码为bytes
       5 print(date)
       6 print(f.getvalue())
       7 
       8 输出:
       9 6
      10 b'xe4xb8xadxe6x96x87'

    三、操作文件和目录

    • 使用os模块可直接调用操作系统提供的接口函数
      1 import os
      2 print(os.name)
      3 
      4 输出:
      5 nt

      如果是posix,说明系统是LinuxUnixMac OS X,如果是nt,就是Windows系统; uname() 函数可查看详细系统信息,Windows上不提供该函数;

    • 环境变量:保存在os.environ变量中,获取某个变量的值可用 os.environ,get('key’) 进行调用;
    • 文件操作:使用 os.path.join() 函数将两个路径合并,可处理不同操作系统的分割符( Windows: ;Linux:/ 
      1 import os
      2 d = os.path.abspath('.')    #查看当前目录的绝对路径
      3 #os.path.join('/Users/michael', 'testdir') #在Linux下创建;
      4 os.path.join('C:\Users\F·iy\Desktop','testdir') #创建新目录,先表示出新目录的完整路径;
      5 os.mkdir('C:\Users\F·iy\Desktop\testdir')   #创建目录
      6 os.rmdir('C:\Users\F·iy\Desktop\testdir')   #删除目录

      使用 os.path.split() 函数对路劲拆分为两部分,后部分为最后的文件目录或文件名; os.path.splitext() 函数可得到文件扩展名; os.rename() 对文件重命名

      1 os.path.split('C:\Users\F·iy\Desktop\testdir')
      2 os.path.splitext('test.py')         #得到('test', '.py')
      3 os.rename('test.txt','test.py')     #将.txt改为.py文件
      4 os.remove('test.py')                #删掉文件
      1 #列出当前目录下的所有文件
      2 a = [x for x in os.listdir('.') if os.path.isdir(x)]
      3 #列出所有的.py文件
      4 b = [x for x in os.listdir('.') if os.path.splitext(x)[1]=='.py']
      5 print(a,b)
      6 
      7 输出:
      8 ['__pycache__']   ['func.py', 'test.py', '__init__.py']

    四、序列化

      把变量从内存中变成可存储或传输的过程;(特定的序列化称为pickling)

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

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

     1 #使用pickle.dump()与pickle.load()
     2 
     3 import pickle
     4 d = dict(name='jack',age=18)
     5  #直接把对象序列化后写入一个file-like Object(one.txt)里;
     6 f = open('one.txt','wb')
     7 pickle.dump(d,f)
     8 f.close()
     9 #从一个file-like Object里直接反序列化出对象
    10 f = open('one.txt','rb')
    11 d = pickle.load(f)
    12 print(d)
    13 
    14 输出:
    15 {'name': 'jack', 'age': 18}
     1 #使用pickle.dumps() 与pickle.loads()
     2 
     3 import pickle
     4 d = dict(name='jack',age=18)
     5 a = pickle.dumps(d)     #把任意对象序列化成一个bytes
     6 b = pickle.loads(a)     #反序列化出对象
     7 print(a)
     8 print(b)
     9 
    10 输出:
    11 b'x80x03}qx00(Xx04x00x00x00nameqx01Xx04x00x00x00jackqx02Xx03x00x00x00ageqx03Kx12u.'
    12 {'name': 'jack', 'age': 18}
    • JSON:序列化的标准格式  json模块  更通用、更符合web标准。
       1 #使用json.dumps()与json.loads()
       2 
       3 import json
       4 d = dict(name='Bob', age=20, score=88)
       5 a = json.dumps(d)   #直接返回一个str
       6 b = json.loads(a)    #反序列化
       7 print(a)
       8 print(b)
       9 
      10 输出:
      11 {"name": "Bob", "age": 20, "score": 88}
      12 {'name': 'Bob', 'age': 20, 'score': 88}    
       1 import json
       2 d = dict(name='Bob', age=20)
       3 #创建文件
       4 f = open('text.txt','w')
       5 json.dump(d,f)
       6 #反序列化
       7 f = open('text.txt','r')
       8 b = json.load(f)
       9 print(b)
      10 
      11 输出:
      12 {'name': 'Bob', 'age': 20
    • 序列化 class 类,先将其转化为  dict  形式,使用 default 转换为可序列对象;反序列化时用 loads() 转换出一个dict对象后,使用 object_hook负责把 dict 转换为 Student 实例 
       1 import json
       2 
       3 class Student(object):
       4     def __init__(self, name, age, score):
       5         self.name = name
       6         self.age = age
       7         self.score = score
       8 
       9     def get(self):
      10         return '%s age is %s ,score:%s'% (self.name,self.age,self.score)
      11 #为class写一个转换函数
      12 def student_dict(std):
      13         return {
      14             'name': std.name,
      15             'age': std.age,
      16             'score': std.score
      17         }
      18 
      19 s = Student('jack', 18, 90)
      20 a = json.dumps(s, default=student_dict) #可选参数default可把任意一个对象变成一个可序列为JSON的对象
      21 #将class的实例变为dict,通常class的实例都有一个__dict__属性
      22 # print(json.dumps(s, default=lambda obj: obj.__dict__))
      23 print(a)
      24 
      25 #反序列化为class类的对象实例,先转换为dict后再转为实例
      26 def dict_student(d):
      27     return Student(d['name'], d['age'], d['score'])
      28 b = json.loads(a,object_hook=dict_student)
      29 print(b)    #实例对象
      30 print(b.get())  
      31 
      32 输出:
      33 {"name": "jack", "age": 18, "score": 90}
      34 <__main__.Student object at 0x000000B529F2C908>
      35 jack age is 18 ,score:90
  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/liqiongming/p/10085342.html
Copyright © 2011-2022 走看看