文章目录

  • 介绍
  • 磁盘文件
  • `open`函数
  • with 语句
  • 文件读取函数
  • 文件位置
  • 标准 I/O
  • 标准输入
  • 标准输出
  • 标准IO的重定向和恢复
  • 对象的序列化和反序列化
  • 方法
  • 实例


Python 08-文件读写

介绍

本文介绍 Python 如何处理文件以及标准输入和输出,我们将展示如何从文件读取和写入文件。

Python 中的所有内容都是一个对象,UNIX 中的所有内容都是文件。

磁盘文件

open函数

内置函数,属于IO模块。open()返回一个file对象,该对象的类型取决于模式,并通过该对象执行标准文件操作。

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
  • file是要打开的文件的名称。
  • mode是一个可选字符串,指定打开文件的模式。它默认为“r”,表示以文本模式打开阅读。

模式

含义

'r'

读取(默认)

'w'

写入

'X'

创建一个新文件并打开它进行写入

'a'

追加

'b'

二进制数据

‘t’

文本模式(默认)

'+'

打开磁盘文件进行更新(读写)

  • buffering是用于设置缓冲策略的可选整数。
  • encoding是用于解码或编码文件的编码名称,默认是平台的编码
  • errors是一个可选的字符串,它指定如何处理编码和解码错误。
  • newline控制换行符的行为 : None, ‘’, ‘\n’, ‘\r’, 和 ‘\r\n’.
  • closefd为False,则在关闭文件时,底层文件描述符将保持打开状态。当给定文件名时,这不起作用,在这种情况下必须为True。
  • 通过将可调用函数传递为opener,可以使用自定义的opener。然后用(fileflags)调用opener获得文件对象的底层文件描述符opener必须返回一个打开的文件描述符(将os.open作为opener传递会导致类似于传递None的功能)。

在文本模式下读取时,默认会把平台特定的行结束符 (Unix 上的 \n, Windows 上的 \r\n) 转换为 \n。在文本模式下写入时,默认会把出现的 \n 转换回平台特定的结束符。这样在幕后修改文件数据对文本文件来说没有问题,但是会破坏二进制数据例如 JPEGEXE 文件中的数据。请一定要注意在读写此类文件时应使用二进制模式。

也可以使用字符串或bytearray作为文件进行读写。对于字符串,StringIO可以像在文本模式下打开的文件一样使用,对于字节,BytesIO可以像在二进制模式下打开的文件一样使用。

# 默认编码
>>> f = open("openpyxl 01 安装.md")
>>> f
<_io.TextIOWrapper name='openpyxl 01 安装.md' mode='r' encoding='cp936'>

# 指定编码
>>> f = open("openpyxl 01 安装.md",encoding="utf8")
>>> f
<_io.TextIOWrapper name='openpyxl 01 安装.md' mode='r' encoding='utf8'>

with 语句

在处理文件对象时,最好使用 with 关键字。

  • 优点是当子句体结束后文件会正确关闭,即使在某个时刻引发了异常。
  • 使用 with 相比等效的 try-finally 代码块要简短得多,处理文件通常会导致错误;
  • with语句通过封装通用的准备和清除任务来简化异常处理。
with open('workfile') as f:
      read_data = f.read()

文件读取函数

  • read(n=-1)函数
    从文件中读取指定数量的字节。 如果未指定字节数,它将读取整个文件。
>>> with open('hello.txt', 'r') as f:
...     f.read(3)
...     f.read()
...
'hel'
'lo world\n你好,中国'
  • readline()方法
    从文件读取一行。 字符串中保留尾随换行符。 函数到达文件末尾时,将返回一个空字符串。
>>> with open('hello.txt', 'r') as f:
...     f.readline()
...     f.readline()
...
'hello world\n'
'你好,中国'
  • readlines()方法
    读取数据,直到文件结尾,然后返回行列表。
>>> with open('hello.txt', 'r') as f:
...     content = f.readlines()   # 返回行列表,每行包含换行符
...
>>> for x in content:
...     print(x.strip())		# 打印每行,用str.strip() 去除空白字符,包括换行 
...
hello world
你好,中国
  • num = write()方法
    将字符串写入文件, 返回字节数
>>> with open('hello.txt', 'w') as f:
...     f.write("hello world\n") # 12
...     f.write("你好,中国")			# 5
...
12
5

文件位置

文件位置是我们从中读取数据的文件位置。

  • tell()方法给出文件中的当前位置
>>> with open('hello.txt', 'r') as f:
...     f.read(5) # 读5个字符
...     f.tell()  # 当前位置为5
...
'hello'
5
  • seek(offset, whence=0, /)方法移动文件中的位置。
    whence 选项:
* 0 -- 流始端(默认值);偏移量应为零或正
* 1 -- 当前流位置;偏移量可能为负
* 2 -- 流末端;偏移量通常为负
>>> with open('hello.txt', 'r') as f:
...     f.read(5)
...     f.tell()
...     f.seek(10)
...     f.read()
...
'hello'
5
10
'd\n你好,中国'

标准 I/O

基本的 I/O 连接共有三种:标准输入,标准输出和标准错误。

Python 中的标准输入和输出是sys模块中的对象。

对象

描述

sys.stdin

标准输入是进入程序的数据。 标准输入来自键盘。

sys.stdout

标准输出是我们使用 print 关键字打印数据的地方。

sys.stderr

标准错误是程序写入错误消息的流。 通常是文本终端。

符合 UNIX 的哲学,标准 I/O 流 文件对象。

标准输入

stdin 用于所有交互式输入(包括对 input() 的调用);

import sys
print('Enter your name: ', end='')
name = ''
sys.stdout.flush()
while True:
    c = sys.stdin.read(1)
    if c == '\n':
        break
    name = name + c
print('Your name is:', name)

但是,通常为了获得输入,使用更高级别的函数:input() 。

>>> data = input("What's your name ? ")
What's your name ? Peter
>>> print(f"Welcom {data}")
Welcom Peter
>>> print(f"Welcom {data:^10}")
Welcom   Peter

标准输出

  • stdout 用于 print() 和 expression 语句的输出,以及用于 input() 的提示符;
>>> import sys
>>> sys.stdout.write('Honore de Balzac, Father Goriot\n')
Honore de Balzac, Father Goriot
32
  • 通常使用print函数
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
  • 默认情况下,print函数将文本输出到sys.stdout
print('Honore de Balzac')
print('The Splendors and Miseries of Courtesans', 'Gobseck', 'Father Goriot', sep=":")

vals = [1, 2, 3, 4, 5]

for e in vals:
    print(e, end=' ')
print()
  • print()函数包含一个file参数,该参数告诉我们在哪里打印数据。所以可以使用print()函数写入文件。
with open('works.txt', 'w') as f:
    print('Beatrix', file=f)
    print('Honorine', file=f)
    print('The firm of Nucingen', file=f)

标准错误输出和标准错误差不多,都是数据的流出对象,略。

标准IO的重定向和恢复

标准输出可以重定向。 在以下示例中,我们将标准输出重定向到常规文件。

  • 脚本中,我们将标准输出重定向到常规文件output.txt
  • 然后,恢复原始的标准输出。 std.output的原始值保存在特殊的sys.__stdout__变量中。
import sys

with open('output.txt', 'w') as f:

    sys.stdout = f

    print('Lucien')
    sys.stdout.write('Rastignac\n')
    sys.stdout.writelines(['Camusot\n', 'Collin\n'])

    sys.stdout = sys.__stdout__

    print('Bianchon')
    sys.stdout.write('Lambert\n')

对象的序列化和反序列化

模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。

  • “pickling” 是将 Python 对象及其所拥有的层次结构转化为一个字节流的过程,
  • “unpickling” 是相反的操作,会将(来自一个 binary file 或者 bytes-like object 的)字节流转化回一个对象层次结构。

pickling(和 unpickling)也被称为“序列化”, “编组” 或者 “平面化”。为避免混乱,采用术语 “封存 (pickling)” 和 “解封 (unpickling)”。

注解

序列化是一种比持久化更底层的概念,虽然 pickle 读取和写入的是文件对象,但它不处理持久对象的命名问题,也不处理对持久对象的并发访问(甚至更复杂)的问题。pickle 模块可以将复杂对象转换为字节流,也可以将字节流转换为具有相同内部结构的对象。处理这些字节流最常见的做法是将它们写入文件,但它们也可以通过网络发送或存储在数据库中。shelve 模块提供了一个简单的接口,用于在 DBM 类型的数据库文件上封存和解封对象。

pickle : 有泡菜、腌渍的意思
pickling:就解释成酸洗、腌渍
unpickling:解释成解腌

方法

  • 使用dump()方法腌制对象。
dump(object, file)
dumps(object) -> string
  • 使用load()方法解开对象。
load(file) -> object
loads(string) -> object

实例

#!/usr/bin/env python

# pickle_ex.py

import pickle

class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        return self.name

    def get_age(self):
        return self.age

person = Person('Monica', 15)
print(person.get_name())
print(person.get_age())

with open('monica', 'wb') as f:
    pickle.dump(person, f)

with open('monica', 'rb') as f2:
    monica = pickle.load(f2)

print(monica.get_name())
print(monica.get_age())