Originally I wrote PyZ3950 to support Tyrannioware, my home book cataloging program. The Cheshire Project at the University of Liverpool adopted it, and I would like to acknowledge their financial support and Rob Sanderson's contributions as co-developer. The ASN.1 and Z39.50 modules are distributed together partly for my convenience, and partly because the Z39.50 code may serve as an illustration of the ASN.1 API. (I wrote my own ASN.1 code because I wanted its client to be able to use normal Python data types, and use ASN.1 specifications run through the included compiler: neither PySNMP nor Pisces offer this.) The only other Python Z39.50 implementation I know of is part of a larger commercial product, wxPresso.

There's also a MARC module in zmarc.py (handles parsing only), and a graphical Zthes browser as an example.

The software requires Python 2.2 or later, and is licensed under the X licence (details in the files themselves), but the zoom interface requires Dave Beazley's PLY package, licensed under the LGPL. Click here to download version 2.04 of PyZ3950. It's packaged with distutils, so unzip and untar, and then python setup.py install. Most development has been done under Linux, but I've tested briefly under Win98 (and, in theory, the code should run anywhere Python runs). The CVS repository is at sourceforge.


Link to pydoc documentation for zoom implementation (recommended interface).


PyZ3950 currently is capable of sending and receiving v2 or v3 PDUs Initialize, Search, Present, Scan, Sort, Close, and Delete. For client work, you probably want to use ZOOM, which should be in the same distribution as this file, in zoom.py. The Server class in this file implements a server, but could use some work. Both interoperate with the Yaz toolkit and the client interoperates with a variety of libraries.

Useful resources:


asn1 is a relatively general-purpose ASN.1 BER encoder and decoder. Encoding and decoding functions (asn1.encode and asn1.decode) take an ASN.1 spec, and transform back and forth between a byte stream and what I consider a natural Python representation of the data.

Separating the ASN.1 specification from the code would allow compilation of the specification to inline Python or C code, or to a specification for a C-based engine.

This module supports the following ASN.1 types:

For all the above types, the ASN.1 spec is just the name of the type. Inherently constructed types:

For CHOICE, the Python representation is (name, val). For SEQUENCE, on decoding, the Python representation is an instance of an asn1-synthesized class. On encoding, any class with the appropriate attributes is acceptable, calling the SEQUENCE specification but you can obtain a fresh instance of the synthesized class by calling the SEQUENCE specification: this class overrides setattr to provide attribute-name error checking. (The rationale for the seemingly unPythonic errorchecking is that misspelled optional attributes would otherwise be hard to detect. If you don't like it, it should be easy to turn off.)

The definition of enumerated values for INTEGER and BITSTRING types is supported via the compiler (or see their definitions). For BITSTRING types, __getitem__ (value_name) and __setitem__ (value_name) are implemented as BitStringVal methods, allowing, e.g., bitstringval['version_1'] = 1, or if bitstringval['version_1']. An appropriate BitStringVal for encoding can be constructed by calling the specification. For INTEGER types, call get_num_from_name (name) or get_name_from_num(num) methods of the type specification. (Note that code like if val == defn.get_num_from_name ('failure'): is less prone to typo-induced errors than if failure' == defn.get_name_from_num (val):

In order to obtain definitions nested inside other definitions (e.g. INTEGER and BITSTRING, above), __getitem__ methods are provided for SEQUENCE, CHOICE, and SEQUENCE_OF. For SEQUENCE and CHOICE, the key is the name of the sequence element or arm (respectively). For SEQUENCE_OF, the key is 0 (arbitrarily chosen).

APPLICATION and PRIVATE class tags are supported via the compiler, or pass the cls= keyword to IMPLICIT or EXPLICIT.

For examples, see the test code at the end of this file, or the Z39.50 code that should be distributed with this file as part of PyZ3950.

There is not yet support for:

Useful ASN.1 references:

Acknowledgement: Index Data's C Z39.50 implementation, Yaz, has been invaluable for doing interoperability testing on my local machine.

If you have any questions, bug reports, feature requests, or whatever, email Aaron Lav

Aaron's Home Page