【Python3 笔记】Python3 I/O编程 文件读写 内存读写 目录操作 序列化

本文深入探讨了Python中的I/O编程,包括文件读写、内存读写、文件目录操作以及序列化等核心主题。文章详细介绍了如何使用with open进行文件操作,内存读写的实现,以及操作文件和目录的技巧。同时,还讲解了序列化的概念及其在Python中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列是学习 廖雪峰 Python3 教程 过程中记录的笔记,本篇文章记录 Python 中的 I/O 编程,主要内容有文件的读写、内存的读写、对文件及目录的操作,以及两种常见的序列化操作。

I/O 编程

  • 基本概念:input , output , stream
  • 存在问题:输入和接收速度不匹配;
  • 解决方法:同步(等待 I/O 的执行结果)、异步(回调–好了叫我,轮询—好了没…好了没);
  • 收获新知:编程语言都会把操作系统提供的低级C接口封装起来方便使用;

文件读写

  • with open 的方式代码更加简洁,该方法会自动调用 f.close()

  • f.read() 会一次性读取文件的全部内容,如果不确定文件大小,建议反复调用 f.read(size) ,每次最多读取 size 个字节;

    with open('/path/to/file', 'r') as f:
        print(f.read())
    
  • 对于二进制文件,打开的模式为 rb

  • 对于非 UTF-8 的文件,需要传入 encoding 参数;

  • 对于编码不规范的文件,可能会遇到非法编码的字符,最简单的处理方式是直接忽略;

    with open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore') as f:
        print(f.read())
    
  • 写文件:常用标识符 w 直写(会覆盖原文件的内容)、wb 直写二进制文件按、a 追加;

内存读写

  • StringIO 在内存中读写 str ;

  • BytestIO 在内存中读写 字节;

  • 内存写入的内容是否被及时读取、何时会被覆盖,都需要很仔细的查看;

    from io import StringIO
    
    f = StringIO("Hi! I'm Morton wang.")
    print("f.getvalue():", f.getvalue())
    f.write('hello')
    f.write(' ')
    f.write('world!')
    print("f.getvalue():", f.getvalue())
    
    output—————————————————————————
    f.getvalue(): Hi! I'm Morton wang.
    f.getvalue(): hello world!on wang.
    
    from io import BytesIO
    
    f = BytesIO()
    f.write('Python大法好'.encode('utf-8'))
    print("f.read():", f.read())
    print("f.getvalue():", f.getvalue())
    # 使用 'Python大法好' 的字节码初始化
    f2 = BytesIO(b'Python\xe5\xa4\xa7\xe6\xb3\x95\xe5\xa5\xbd')
    f2.write('中国'.encode('utf-8'))
    print("f2.read():", f2.read().decode('utf-8'))
    print("f2.getvalue():", f2.getvalue().decode('utf-8'))
    
    output———————————————————————————
    f.read(): b''
    f.getvalue(): b'Python\xe5\xa4\xa7\xe6\xb3\x95\xe5\xa5\xbd'
    f2.read(): 大法好
    f2.getvalue(): 中国大法好
    

操作文件和目录

  • 获得系统类型( nt 表示 Windows)、指定的环境变量;

    import os
    
    print(os.name)
    print(os.environ.get('CPATH'))
    
    output————————————————————————
    nt
    C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\include
    
  • 目录部分:路径合并、拆分函数分别使用 os.path.join(path_1, path_2) os.path.split(path) ,好处就是可以避免不同操作系统的路径不同带来的麻烦,这些函数仅对字符串进行操作,不要求该路径一定存在;

  • 目录部分:os.path.isfile(path) os.path.isdir(path) 分别用来判断该路径是否是文件、目录;

  • 文件部分:文件重命名、删除文件;

    import os
    
    # 查看当前目录的绝对路径:
    absolute_path = os.path.abspath('.')
    print('absolute_path:\t', absolute_path)
    # 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
    new_path = os.path.join(absolute_path, 'testdir')
    print('new_path:\t\t', new_path)
    # 然后创建一个目录:
    os.mkdir(new_path)
    # 删掉一个目录:
    os.rmdir(new_path)
    
    # os.path.split 后一部分是最后级别的目录或者文件名
    print(os.path.split('/path/to/file.txt'))
    print(os.path.split('/path/to/file'))
    # os.path.splitext 可以获取文件的拓展名
    print(os.path.splitext('/path/to/file.txt'))
    print(os.path.splitext('/path/to/file'))
    
    # 文件重命名
    os.rename('test.txt', 'test.py')
    # 文件删除
    os.remove('test.py')
    
    output————————————————————————
    absolute_path:	 F:\wtlGit\python3_notes
    new_path:		 F:\wtlGit\python3_notes\testdir
    ('/path/to', 'file.txt')
    ('/path/to', 'file')
    ('/path/to/file', '.txt')
    ('/path/to/file', '')
    

序列化

  • 把变量从内存中变成可存储或传输的过程称之为序列化,反过来就是反序列化;

  • 序列化为字节码及对应的反序列化:pickle.dumps(object) pickle.loads(dumps)

    import pickle
    
    student = dict(name='Bob', age=20, score=88)
    student_dumps = pickle.dumps(student)
    student_1 = pickle.loads(student_dumps)
    print("student_dumps:", student_dumps)
    print("student_1:\t", student_1)
    
    output————————————————————
    student_dumps: b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'
    student_1:	 {'name': 'Bob', 'age': 20, 'score': 88}
    
  • 序列化到文件及对应的反序列化:pickle.dump(object, file) pickle.load(dump_file)

    import pickle
    
    student = dict(name='Bob', age=20, score=88)
    with open('dump.txt', 'wb') as f:
        pickle.dump(student, f)
    
    with open('dump.txt', 'rb') as f:
        student_1 = pickle.load(f)
    
    print("student:\t", student)
    print("student_1:\t", student_1)
    
    output————————————————————
    student:	 {'name': 'Bob', 'age': 20, 'score': 88}
    student_1:	 {'name': 'Bob', 'age': 20, 'score': 88}
    
  • JSON 是序列化的标准格式,可以在不同的编程语言之间传递对象,并且比XML更快,而且可以直接在Web页面中读取,非常方便;

  • JSON 标准规定 JSON 编码是 UTF-8 ,表示出来就是一个字符串;

  • pickle 的使用类似,JSON 也支持序列化到变量和文件,更多的参数使用 在这里

    import json
    
    class Student(object):
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            self.score = score
    
        def __str__(self):
            return "name:{} age:{} score:{}".format(self.name, self.age, self.score)
    
    def student2dict(std):
        return {
            'name': std.name,
            'age': std.age,
            'score': std.score
        }
    
    def dict2student(d):
        return Student(d['name'], d['age'], d['score'])
    
    s = Student('Bob', 20, 88)
    # json 不能直接序列化对象,需要将对象变为 Dict
    s_json = json.dumps(s, default=student2dict)
    print(s_json)
    print(json.dumps(s, default=lambda obj: obj.__dict__))  # 效果同上
    print(json.loads(s_json, object_hook=dict2student))     # object2str()
    
    output——————————————————————————————————
    {"name": "Bob", "age": 20, "score": 88}
    {"name": "Bob", "age": 20, "score": 88}
    name:Bob age:20 score:88
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值