18.10. 多文件—支持包含不同部分的文件
从版本 2.5 开始不推荐使用:email软件包应优先于multifile模块使用。仅提供此模块是为了保持向后兼容性。
MultiFile对象使您可以将文本文件的各个部分视为类似于文件的 Importing 对象,当遇到给定的定界符模式时,readline()返回''
。此类的默认设置旨在使它可用于解析 MIMEMultipart 消息,但是pass将其子类化并覆盖方法,可以轻松地将其改编为更广泛的用途。
-
- class *
multifile.
MultiFile
(* fp * [,* seekable *])
- class *
MultiFile仅查看 Importing 对象的readline(),seek()和tell()方法,仅当您要随机访问各个 MIME 部分时才需要后两个方法。要在不可搜索的流对象上使用MultiFile,请将可选的* seekable *参数设置为 false;这将防止使用 Importing 对象的seek()和tell()方法。
知道在MultiFile的世界视图中,文本由三行组成:数据,节分隔符和结束标记。 MultiFile 旨在支持对可能具有多个嵌套消息部分的消息进行解析,每个消息部分都有其自己的节分割线和结束标记线模式。
18.10.1. 多文件对象
MultiFile实例具有以下方法:
-
MultiFile.
readline
(* str *)- 阅读一行。如果该行是数据(不是分节符,结束标记或实际的 EOF),则将其返回。如果该行与最近堆叠的边界匹配,则返回
''
并将self.last
设置为 1 或 0,因为该匹配是结束标记还是不是结束标记。如果该线与任何其他堆叠边界匹配,则引发错误。遇到基础流对象上的文件结尾时,除非所有边界都被弹出,否则该方法将引发Error
。
- 阅读一行。如果该行是数据(不是分节符,结束标记或实际的 EOF),则将其返回。如果该行与最近堆叠的边界匹配,则返回
-
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 边界都具有的
'-
-'
以外的前缀,但已语句它以便可以在派生类中覆盖它。
- 如果* str *是数据,则返回 true;如果它可能是截面边界,则返回 false。如所写,它在行首测试所有 MIME 边界都具有的
请注意,此测试旨在用作实际边界测试的快速防护。如果它始终返回 false,则只会减慢处理速度,而不会导致失败。
MultiFile.
push
(* str *)
可以推动多个边界。遇到最近推入的边界将返回 EOF;遇到任何其他边界都会引发错误。
-
MultiFile.
pop
( )- 弹出截面边界。该边界将不再被解释为 EOF。
-
MultiFile.
section_divider
(* str *)- 将边界变成截面分割线。默认情况下,此方法加
'--'
(MIME 节边界具有此前缀),但已语句该方法,因此可以在派生类中覆盖它。此方法不需要附加 LF 或 CR-LF,因为与结果的比较将忽略尾随空白。
- 将边界变成截面分割线。默认情况下,此方法加
-
MultiFile.
end_marker
(* str *)- 将边界字符串变成结束标记线。默认情况下,此方法加
'--'
并附加'--'
(就像 MIME-multipart-message 结束标记)一样,但是已语句它,因此可以在派生类中覆盖它。此方法不需要附加 LF 或 CR-LF,因为与结果的比较将忽略尾随空白。
- 将边界字符串变成结束标记线。默认情况下,此方法加
最后,MultiFile个实例具有两个公共实例变量:
-
MultiFile.
level
- 当前 Component 的嵌套深度。
-
MultiFile.
last
- 如果最后一个文件结尾是消息结尾标记,则为 true。
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()