python-hl7 – HL7 v2.x Message Parser

raw JSON →
0.4.5 verified Tue May 12 auth: no python install: verified quickstart: verified

A simple Python library for parsing HL7 v2.x messages. Provides segment, field, and component-level access to HL7 messages, along with MLLP (Minimal Lower Layer Protocol) client support. Does not handle HL7 FHIR (v4); it is strictly for the pipe-delimited v2.x wire format.

pip install hl7
error IndexError: list index out of range
cause The HL7 message was not correctly parsed, often due to incorrect segment termination characters (e.g., `\n` instead of `\r`), causing the library to only recognize the first segment or an empty message.
fix
Ensure the HL7 message uses carriage returns (\r) as segment delimiters. If the input string uses newlines (\n), replace them with \r before parsing.
hl7_raw_string = "MSH|^~\\&|...\nPID|...\nOBX|..."
hl7_message = hl7_raw_string.replace('\n', '\r')
parsed_message = hl7.parse(hl7_message)
# Now you can access segments correctly, e.g., parsed_message['PID']
error NameError: name 'MLLPClient' is not defined
cause The `MLLPClient` class is part of the `hl7.client` submodule and is not directly available in the top-level `hl7` module without explicit import.
fix
Import MLLPClient specifically from hl7.client or reference it as hl7.client.MLLPClient.
from hl7.client import MLLPClient

host = '127.0.0.1'
port = 4106

with MLLPClient(host, port) as client:
    client.send_message('test1')

# Alternatively, without explicit import:
# with hl7.client.MLLPClient(host, port) as client:
#     client.send_message('test1')
error AttributeError: 'Message' object has no attribute 'MSH' (or any other segment name)
cause The `hl7.Message` object (from the `python-hl7` library) uses list-like or dictionary-like access for its segments and fields, not direct attribute access like `message.MSH`.
fix
Access segments using integer indices (e.g., message[0] for the first segment) or by segment name as a string key (e.g., message['MSH']).
import hl7

hl7_message_string = "MSH|^~\\&|APP|FAC|APP2|FAC2|202301010800||ADT^A01|MSG123|P|2.5\rPID|1||12345^6^7^^MR^MDC|...\r"
message = hl7.parse(hl7_message_string)

# Correct way to access the MSH segment
msh_segment = message['MSH']
print(msh_segment)

# Accessing by index (MSH is typically the first segment)
pids_segment = message # Assuming PID is the second segment
print(pids_segment)

# Accessing a specific field in a segment (e.g., PID.3)
patient_id = message['PID']
print(patient_id)
gotcha HL7 v2.x messages use \r (carriage return) as the segment separator, NOT \n. Messages with \n line endings will not parse correctly.
fix Ensure raw messages use \r: raw = raw.replace('\n', '\r') before parsing.
breaking The 'mllp' installation extra was removed along with the synchronous MLLPClient class in 0.4.0. MLLP functionality is now async-only and does not require a separate 'mllp' extra. Attempting to install `hl7[mllp]` on versions >= 0.4.0 will result in a warning.
fix Migrate to async: reader, writer = await open_hl7_connection(host, port). The async MLLP functionality is now part of the base `hl7` package and does not require the `[mllp]` extra.
gotcha This library only handles HL7 v2.x pipe-delimited messages. It does NOT support HL7 FHIR (v4 JSON/XML). Use fhir.resources or fhirclient for FHIR.
fix Use the fhir.resources package for FHIR R4/R5 resources.
gotcha Field indexing is 0-based on the segment object but MSH segment counts the field separator as MSH.1, so MSH[1] returns '|' and MSH[9] returns the message type. This 1-off confusion is common.
fix Use the string accessor message['MSH.9'] for clarity, or remember segment()[n] is 0-indexed.
gotcha Accessing a non-existent segment with message.segment('ZZZ') raises KeyError, not returning None.
fix Check segments first: if message.segments('ZZZ'): ... or wrap in try/except KeyError.
pip install hl7[mllp]
python os / libc variant status wheel install import disk
3.10 alpine (musl) hl7 - - 0.02s 18.0M
3.10 alpine (musl) mllp - - 0.02s 18.0M
3.10 slim (glibc) hl7 - - 0.01s 18M
3.10 slim (glibc) mllp - - 0.01s 18M
3.11 alpine (musl) hl7 - - 0.05s 19.9M
3.11 alpine (musl) mllp - - 0.04s 19.9M
3.11 slim (glibc) hl7 - - 0.04s 20M
3.11 slim (glibc) mllp - - 0.04s 20M
3.12 alpine (musl) hl7 - - 0.03s 11.7M
3.12 alpine (musl) mllp - - 0.03s 11.7M
3.12 slim (glibc) hl7 - - 0.03s 12M
3.12 slim (glibc) mllp - - 0.03s 12M
3.13 alpine (musl) hl7 - - 0.03s 11.4M
3.13 alpine (musl) mllp - - 0.03s 11.4M
3.13 slim (glibc) hl7 - - 0.03s 12M
3.13 slim (glibc) mllp - - 0.03s 12M
3.9 alpine (musl) hl7 - - 0.02s 17.5M
3.9 alpine (musl) mllp - - 0.02s 17.5M
3.9 slim (glibc) hl7 - - 0.02s 18M
3.9 slim (glibc) mllp - - 0.02s 18M

Parse an HL7 v2.x message and access segments and fields.

import hl7

raw = 'MSH|^~\\&|SND|SND_FAC|RCV|RCV_FAC|20230101120000||ADT^A01|MSG00001|P|2.3\rPID|||12345^^^MRG||DOE^JOHN||19800101|M\r'
message = hl7.parse(raw)

# Access fields using segment(field) notation
print(message.segment('MSH'))       # Full MSH segment
print(message['MSH.9'])              # Message type: ADT^A01
print(message['PID.5'])              # Patient name: DOE^JOHN
print(message.segment('PID')[5])     # Same: DOE^JOHN