# 14.4. `xdrlib` - 对XDR数据进行编码和解码

源代码： Lib / xdrlib.py

`xdrlib`模块支持由Sun Microsystems，Inc.于1987年6月编写的 RFC 1014中描述的外部数据表示标准。它支持RFC中描述的大多数数据类型。

`xdrlib`模块定义了两个类，一个用于封装变量为XDR表示，另一个用于XDR表示的分拆。还有两个异常类。

class `xdrlib.``Packer`

  `Packer`是封装数据到XDR表示形式的类。`Packer`类实例化时没有参数。

class `xdrlib.``Unpacker`(data)

  `Unpacker`是从字符串缓冲区解包XDR数据值的互补类。输入缓冲区为data。

也可以看看

RFC 1014 - XDR：外部数据表示标准
  此RFC定义了在最初写入此模块时为XDR的数据的编码。它显然已被 RFC 1832废弃。
RFC 1832 - XDR：外部数据表示标准
  较新的RFC，提供了XDR的修订定义。

## 14.4.1. Packer Objects

`Packer`实例具有以下方法：

`Packer.``get_buffer`()

  以字符串形式返回当前封装缓冲区。

`Packer.``reset`()

  将封装缓冲区重置为空字符串。

通常，您可以通过调用相应的`pack_type()`方法封装任何最常见的XDR数据类型。每个方法接受一个参数，值为封装。The following simple data type packing methods are supported: `pack_uint()`, `pack_int()`, `pack_enum()`, `pack_bool()`, `pack_uhyper()`, and `pack_hyper()`.

`Packer.``pack_float`(value)

  打包单精度浮点数值。

`Packer.``pack_double`(value)

  打包双精度浮点数值。

以下方法支持封装字符串，字节和不透明数据：

`Packer.``pack_fstring`(n, s)

  打包固定长度的字符串s。 n是字符串的长度，但它不打包到数据缓冲区。如果需要，字符串用空字节填充以保证4字节对齐。

`Packer.``pack_fopaque`(n, data)

  类似于`pack_fstring()`，包装固定长度的不透明数据流。

`Packer.``pack_string`(s)

  打包可变长度字符串s。字符串的长度首先作为无符号整数打包，然后用`pack_fstring()`打包该字符串数据。

`Packer.``pack_opaque`(data)

  类似于`pack_string()`包装一个可变长度的不透明数据字符串。

`Packer.``pack_bytes`(bytes)

  类似于`pack_string()`包装一个可变长度的字节流。

以下方法支持封装数组和列表：

`Packer.``pack_list`(list, pack_item)

  包装同质物品的列表。此方法对于具有不确定大小的列表很有用；即：在整个列表已经遍历之前，该大小不可用。对于列表中的每个项目，首先打包无符号整数`1`，后跟数组值。pack_item是用于封装单个项目的函数。在列表的末尾，打包无符号整数`0`。

  例如，要封装整数列表，代码可能如下所示：

      import xdrlib
      p = xdrlib.Packer()
      p.pack_list([1, 2, 3], p.pack_int)

`Packer.``pack_farray`(n, array, pack_item)

  打包均匀项的固定长度列表（数组）。n is the length of the list; it is not packed into the buffer, but a `ValueError` exception is raised if `len(array)` is not equal to n. As above, pack_item is the function used to pack each element.

`Packer.``pack_array`(list, pack_item)

  包含均匀项目的变长列表。首先，列表的长度打包为无符号整数，然后每个元素被打包为`pack_farray()`。

## 14.4.2. Unpacker Objects

`Unpacker`类提供以下方法：

`Unpacker.``reset`(data)

  使用给定的数据重置字符串缓冲区。

`Unpacker.``get_position`()

  返回数据缓冲区中的当前分离位置。

`Unpacker.``set_position`(position)

  将数据缓冲区分离位置设置为位置。您应该小心使用`get_position()`和`set_position()`。

`Unpacker.``get_buffer`()

  以字符串形式返回当前分拆数据缓冲区。

`Unpacker.``done`()

  表示分拆完成。如果所有数据未解压缩，则引发`Error`异常。

此外，可以使用`Packer`打包的每种数据类型都可以使用`Unpacker`解压缩。分拆方法的形式是`unpack_type()`，并且不带参数。它们返回未打包的对象。

`Unpacker.``unpack_float`()

  解包单精度浮点数。

`Unpacker.``unpack_double`()

  类似于`unpack_float()`，打开双精度浮点数。

另外，以下方法分拆字符串，字节和不透明数据：

`Unpacker.``unpack_fstring`(n)

  解包并返回固定长度的字符串。n是预期的字符数。假设填充空字节以保证4字节对齐。

`Unpacker.``unpack_fopaque`(n)

  与`unpack_fstring()`类似，解包并返回固定长度的不透明数据流。

`Unpacker.``unpack_string`()

  解包并返回可变长度的字符串。字符串的长度首先作为无符号整数解包，然后使用`unpack_fstring()`解压缩字符串数据。

`Unpacker.``unpack_opaque`()

  与`unpack_string()`类似，解包并返回可变长度的不透明数据字符串。

`Unpacker.``unpack_bytes`()

  与`unpack_string()`类似，解压缩并返回可变长度的字节流。

以下方法支持分拆数组和列表：

`Unpacker.``unpack_list`(unpack_item)

  解包并返回均匀项目的列表。该列表通过首先拆分无符号整数标志来一次解包一个元素。如果该标志为`1`，则该项目被解包并附加到列表。`0`的标志表示列表的结尾。unpack_item是调用以拆分项目的函数。

`Unpacker.``unpack_farray`(n, unpack_item)

  解包并返回（作为列表）一个固定长度的同质项目数组。n是在缓冲区中期望的列表元素的数量。如上，unpack_item是用于分拆每个元素的函数。

`Unpacker.``unpack_array`(unpack_item)

  解包并返回均匀项的可变长度列表。首先，列表的长度被解包为无符号整数，则每个元素被解包，如在上面的`unpack_farray()`中。

## 14.4.3. Exceptions

此模块中的异常被编码为类实例：

exception `xdrlib.``Error`

  基本异常类。`Error`具有包含错误描述的单个公共属性`msg`。

exception `xdrlib.``ConversionError`

  源自`Error`的类。不包含其他实例变量。

这里是一个例子，你将如何捕获这些异常之一：

    import xdrlib
    p = xdrlib.Packer()
    try:
        p.pack_double(8.01)
    except xdrlib.ConversionError as instance:
        print('packing the double failed:', instance.msg)