18.10. multifile — 支持包含不同部分的文件 — Python 文档
18.10. 多文件 — 支持包含不同部分的文件
MultiFile 对象使您能够将文本文件的部分视为类似文件的输入对象,当给定的分隔符模式为 readline() 时, 将返回遭遇。 此类的默认值旨在使其可用于解析 MIME 多部分消息,但通过将其子类化并覆盖方法,它可以轻松适应更广泛的用途。
- class multifile.MultiFile(fp[, seekable])
创建一个多文件。 您必须使用 MultiFile 实例的输入对象参数实例化此类以从中获取行,例如由 open() 返回的文件对象。
MultiFile 只查看输入对象的 readline()、seek() 和 tell() 方法,后两个是仅当您想要随机访问各个 MIME 部分时才需要。 要在不可搜索的流对象上使用 MultiFile,请将可选的 seekable 参数设置为 false; 这将阻止使用输入对象的 seek() 和 tell() 方法。
知道在 MultiFile 的世界观中,文本由三种行组成:数据、节分隔符和结束标记,这将是有用的。 MultiFile 旨在支持解析可能具有多个嵌套消息部分的消息,每个部分都有自己的节分隔符和结束标记行模式。
18.10.1. 多文件对象
MultiFile 实例具有以下方法:
- MultiFile.readline(str)
- 读一行。 如果该行是数据(不是节分隔符或结束标记或真正的 EOF),则返回它。 如果该行与最近堆叠的边界匹配,则返回
并根据匹配是否为结束标记将
self.last
设置为 1 或 0。 如果该线与任何其他堆叠边界匹配,则引发错误。 在底层流对象上遇到文件结尾时,除非所有边界都已弹出,否则该方法会引发Error
。
- MultiFile.readlines(str)
- 返回此部分中剩余的所有行作为字符串列表。
- MultiFile.read()
- 阅读所有行,直到下一部分。 将它们作为单个(多行)字符串返回。 请注意,这不需要大小参数!
- MultiFile.seek(pos[, whence])
- 寻找。 搜索索引相对于当前部分的开始。 pos 和 whence 参数被解释为文件搜索。
- MultiFile.tell()
- 返回相对于当前节开头的文件位置。
- MultiFile.next()
- 跳到下一部分(即,读取行,直到使用了部分分隔符或结束标记)。 如果有这样的部分,则返回 true,如果看到结束标记,则返回 false。 重新启用最近推送的边界。
- MultiFile.is_data(str)
如果 str 是数据,则返回 true,如果它可能是节边界,则返回 false。 正如所写,它在行首(所有 MIME 边界都有)测试除
'-
-'
之外的前缀,但它被声明为可以在派生类中被覆盖。请注意,此测试旨在作为真实边界测试的快速防护; 如果它总是返回 false,它只会减慢处理速度,而不会导致它失败。
- MultiFile.push(str)
推一个边界字符串。 当发现此边界的装饰版本作为输入行时,它将被解释为节分隔符或结束标记(取决于装饰,请参阅 RFC 2045)。 所有后续读取将返回空字符串以指示文件结束,直到调用 pop() 删除边界 a 或 next() 调用重新启用它。
可以推多个边界。 遇到最近推送的边界会返回EOF; 遇到任何其他边界都会引发错误。
- MultiFile.pop()
- 弹出一个部分边界。 此边界将不再被解释为 EOF。
- MultiFile.section_divider(str)
- 将边界变成分节线。 默认情况下,此方法在
'--'
(MIME 节边界具有)的前面,但它被声明为可以在派生类中被覆盖。 此方法不需要附加 LF 或 CR-LF,因为与结果的比较会忽略尾随空格。
- MultiFile.end_marker(str)
- 将边界字符串转换为结束标记线。 默认情况下,此方法在
'--'
前面加上'--'
(如 MIME 多部分消息结束标记),但它被声明为可以在派生类中覆盖。 此方法不需要附加 LF 或 CR-LF,因为与结果的比较会忽略尾随空格。
最后, MultiFile 实例有两个公共实例变量:
- MultiFile.level
- 当前零件的嵌套深度。
- MultiFile.last
- 如果最后一个文件结束是消息结束标记,则为真。
18.10.2. 多文件例子
import mimetools
import multifile
import StringIO
def extract_mime_part_matching(stream, mimetype):
"""Return the first element in a multipart MIME message on stream
matching mimetype."""
msg = mimetools.Message(stream)
msgtype = msg.gettype()
params = msg.getplist()
data = StringIO.StringIO()
if msgtype[:10] == "multipart/":
file = multifile.MultiFile(stream)
file.push(msg.getparam("boundary"))
while file.next():
submsg = mimetools.Message(file)
try:
data = StringIO.StringIO()
mimetools.decode(file, data, submsg.getencoding())
except ValueError:
continue
if submsg.gettype() == mimetype:
break
file.pop()
return data.getvalue()