18.10. 多文件—支持包含不同部分的文件

从版本 2.5 开始不推荐使用:email软件包应优先于multifile模块使用。仅提供此模块是为了保持向后兼容性。

MultiFile对象使您可以将文本文件的各个部分视为类似于文件的 Importing 对象,当遇到给定的定界符模式时,readline()返回''。此类的默认设置旨在使它可用于解析 MIMEMultipart 消息,但是pass将其子类化并覆盖方法,可以轻松地将其改编为更广泛的用途。

    • class * multifile. MultiFile(* fp * [,* seekable *])
    • 创建一个多文件。您必须使用MultiFile实例的 Importing 对象参数实例化此类,以从中获取行,例如open()返回的文件对象。

MultiFile仅查看 Importing 对象的readline()seek()tell()方法,仅当您要随机访问各个 MIME 部分时才需要后两个方法。要在不可搜索的流对象上使用MultiFile,请将可选的* seekable *参数设置为 false;这将防止使用 Importing 对象的seek()tell()方法。

知道在MultiFile的世界视图中,文本由三行组成:数据,节分隔符和结束标记。 MultiFile 旨在支持对可能具有多个嵌套消息部分的消息进行解析,每个消息部分都有其自己的节分割线和结束标记线模式。

See also

  • Module email

  • 全面的电子邮件处理包;取代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 *)
    • 推送边界字符串。当找到该边界的修饰版本作为 Importing 线时,它将被解释为分节符或结束标记(取决于修饰,请参见 RFC 2045)。所有后续读取将返回空字符串以指示文件结束,直到对pop()的调用删除了边界 a 或next()的调用重新启用了边界。

可以推动多个边界。遇到最近推入的边界将返回 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()