python-hl7 - Easy HL7 v2.x Parsing¶
python-hl7 is a simple library for parsing messages of Health Level 7 (HL7) version 2.x into Python objects. python-hl7 includes a simple client that can send HL7 messages to a Minimal Lower Level Protocol (MLLP) server (mllp_send).
HL7 is a communication protocol and message format for health care data. It is the de-facto standard for transmitting data between clinical information systems and between clinical devices. The version 2.x series, which is often is a pipe delimited format is currently the most widely accepted version of HL7 (there is an alternative XML-based format).
python-hl7 currently only parses HL7 version 2.x messages into an easy to access data structure. The library could eventually also contain the ability to create HL7 v2.x messages.
python-hl7 parses HL7 into a series of wrapped hl7.Container
objects.
The there are specific subclasses of hl7.Container
depending on
the part of the HL7 message. The hl7.Container
message itself
is a subclass of a Python list, thus we can easily access the
HL7 message as an n-dimensional list. Specifically, the subclasses of
hl7.Container
, in order, are hl7.Message
,
hl7.Segment
, hl7.Field
, hl7.Repetition
.
and hl7.Component
.
python-hl7 includes experimental asyncio-based HL7 MLLP support in MLLP using asyncio, which aims to replace txHL7.
Result Tree¶
HL7 Messages have a limited number of levels. The top level is a Message.
A Message is comprised of a number of Fields (hl7.Field
).
Fields can repeat (hl7.Repetition
). The content of a field
is either a primitive data type (such as a string) or a composite
data type comprised of one or more Components (hl7.Component
). Components
are in turn comprised of Sub-Components (primitive data types).
The result of parsing is accessed as a tree using python list conventions:
Message[segment][field][repetition][component][sub-component]
The result can also be accessed using HL7 1-based indexing conventions by treating each element as a callable:
Message(segment)(field)(repetition)(component)(sub-component)
Usage¶
As an example, let’s create a HL7 message:
>>> message = 'MSH|^~\&|GHH LAB|ELAB-3|GHH OE|BLDG4|200202150930||ORU^R01|CNTRL-3456|P|2.4\r'
>>> message += 'PID|||555-44-4444||EVERYWOMAN^EVE^E^^^^L|JONES|196203520|F|||153 FERNWOOD DR.^^STATESVILLE^OH^35292||(206)3345232|(206)752-121||||AC555444444||67-A4335^OH^20030520\r'
>>> message += 'OBR|1|845439^GHH OE|1045813^GHH LAB|1554-5^GLUCOSE|||200202150730||||||||555-55-5555^PRIMARY^PATRICIA P^^^^MD^^LEVEL SEVEN HEALTHCARE, INC.|||||||||F||||||444-44-4444^HIPPOCRATES^HOWARD H^^^^MD\r'
>>> message += 'OBX|1|SN|1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F\r'
We call the hl7.parse()
command with string message:
>>> import hl7
>>> h = hl7.parse(message)
We get a hl7.Message
object, wrapping a series of
hl7.Segment
objects:
>>> type(h)
<class 'hl7.containers.Message'>
We can always get the HL7 message back:
>>> str(h) == message
True
Interestingly, hl7.Message
can be accessed as a list:
>>> isinstance(h, list)
True
There were 4 segments (MSH, PID, OBR, OBX):
>>> len(h)
4
We can extract the hl7.Segment
from the
hl7.Message
instance:
>>> h[3]
[['OBX'], ['1'], ['SN'], [[['1554-5'], ['GLUCOSE'], ['POST 12H CFST:MCNC:PT:SER/PLAS:QN']]], [''], [[[''], ['182']]], ['mg/dl'], ['70_105'], ['H'], [''], [''], ['F']]
>>> h[3] is h(4)
True
Note that since the first element of the segment is the segment name, segments are effectively 1-based in python as well (because the HL7 spec does not count the segment name as part of the segment itself):
>>> h[3][0]
['OBX']
>>> h[3][1]
['1']
>>> h[3][2]
['SN']
>>> h(4)(2)
['SN']
We can easily reconstitute this segment as HL7, using the appropriate separators:
>>> str(h[3])
'OBX|1|SN|1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F'
We can extract individual elements of the message:
>>> h[3][3][0][1][0]
'GLUCOSE'
>>> h[3][3][0][1][0] is h(4)(3)(1)(2)(1)
True
>>> h[3][5][0][1][0]
'182'
>>> h[3][5][0][1][0] is h(4)(5)(1)(2)(1)
True
We can look up segments by the segment identifier, either via
hl7.Message.segments()
or via the traditional dictionary
syntax:
>>> h.segments('OBX')[0][3][0][1][0]
'GLUCOSE'
>>> h['OBX'][0][3][0][1][0]
'GLUCOSE'
>>> h['OBX'][0][3][0][1][0] is h['OBX'](1)(3)(1)(2)(1)
True
Since many many types of segments only have a single instance in a message
(e.g. PID or MSH), hl7.Message.segment()
provides a convienance
wrapper around hl7.Message.segments()
that returns the first matching
hl7.Segment
:
>>> h.segment('PID')[3][0]
'555-44-4444'
>>> h.segment('PID')[3][0] is h.segment('PID')(3)(1)
True
The result of parsing contains up to 5 levels. The last level is a non-container type.
>>> type(h)
<class 'hl7.containers.Message'>
>>> type(h[3])
<class 'hl7.containers.Segment'>
>>> type(h[3][3])
<class 'hl7.containers.Field'>
>>> type(h[3][3][0])
<class 'hl7.containers.Repetition'>
>>> type(h[3][3][0][1])
<class 'hl7.containers.Component'>
>>> type(h[3][3][0][1][0])
<class 'str'>
The parser only generates the levels which are present in the message.
>>> type(h[3][1])
<class 'hl7.containers.Field'>
>>> type(h[3][1][0])
<class 'str'>
MLLP network client - mllp_send
¶
python-hl7 features a simple network client, mllp_send
, which reads HL7
messages from a file or sys.stdin
and posts them to an MLLP server.
mllp_send
is a command-line wrapper around
hl7.client.MLLPClient
. mllp_send
is a useful tool for
testing HL7 interfaces or resending logged messages:
mllp_send --file sample.hl7 --port 6661 mirth.example.com
See mllp_send - MLLP network client for examples and usage instructions.
For receiving HL7 messages using the Minimal Lower Level Protocol (MLLP), take a look at the related twisted-hl7 package. If do not want to use twisted and are looking to re-write some of twisted-hl7’s functionality, please reach out to us. It is likely that some of the MLLP parsing and formatting can be moved into python-hl7, which twisted-hl7 and other libraries can depend upon.
Python 2 vs Python 3 and Unicode vs Byte strings¶
python-hl7 supports Python 3.5+ and primarily deals with the unicode str
type.
Passing bytes to hl7.parse()
, requires setting the
encoding
parameter, if using anything other than UTF-8. hl7.parse()
will always return a datastructure containing unicode str
objects.
hl7.Message
can be forced back into a single string using
and str(message)
.
mllp_send - MLLP network client assumes the stream is already in the correct encoding.
hl7.client.MLLPClient
, if given a str
or
hl7.Message
instance, will use its encoding
method
to encode the unicode data into bytes.
Contents¶
Install¶
python-hl7 is available on PyPi
via pip
or easy_install
:
pip install -U hl7
For recent versions of Debian and Ubuntu, the python-hl7 package is available:
sudo apt-get install python-hl7
Links¶
Documentation: http://python-hl7.readthedocs.org
Source Code: http://github.com/johnpaulett/python-hl7
HL7 References: