Skip to main content

tvnow-epg

A small, dependency-free Python toolkit for working with EPG (Electronic Programme Guide) / XMLTV television schedule data. It parses XMLTV documents into typed dataclasses, lets you filter and search programmes, detects schedule overlaps, normalizes common EPG metadata, and exports normalized schedule information to JSON.

It works entirely on user-supplied EPG data — it performs no network requests, collects nothing, and ships with only synthetic example data.

What the package does

  • Parse XMLTV/EPG schedule documents (files or strings) using Python's standard library.
  • Represent channels and programmes as typed dataclasses with timezone-aware times.
  • Filter programmes by channel and by date/time window.
  • Search programme titles (plain substring or regular expression).
  • Detect overlapping programmes on the same channel.
  • Normalize common EPG metadata (titles, categories).
  • Export normalized schedule data to JSON.

What EPG/XMLTV data is

An Electronic Programme Guide (EPG) is a structured listing of which programmes air on which channels at which times. XMLTV is a widely used XML format for exchanging such listings between systems. A typical XMLTV document has a <tv> root containing <channel> elements and <programme> elements with start/stop timestamps:

<tv>
  <channel id="example.news">
    <display-name>Example News HD</display-name>
  </channel>
  <programme start="20240610060000 +0000" stop="20240610090000 +0000"
             channel="example.news">
    <title>Morning News Desk</title>
    <category>News</category>
  </programme>
</tv>

Installation

pip install tvnow-epg

Requires Python 3.9+. There are no third-party dependencies.

Quick-start example

from tvnow_epg import parse_xmltv_file, filter_by_channel, to_json

schedule = parse_xmltv_file("data/sample_epg.xml")

for channel in schedule.channels:
    print(channel.channel_id, "-", channel.display_name)

programmes = filter_by_channel(schedule.programmes, "example.news")
for p in programmes:
    print(p.start, "-", p.title)

print(to_json(schedule, channel_id="example.news"))

Parsing an XMLTV file

from tvnow_epg import parse_xmltv, parse_xmltv_file

# From a file path
schedule = parse_xmltv_file("guide.xml")

# From a string or bytes you already have in memory
with open("guide.xml", "rb") as fh:
    schedule = parse_xmltv(fh.read())

schedule is a Schedule holding .channels (list of Channel) and .programmes (list of Programme, sorted by channel then start time).

Listing channels

for channel in schedule.channels:
    print(channel.channel_id)   # e.g. "example.news"
    print(channel.display_name) # e.g. "Example News HD"
    print(channel.icon)         # optional icon URL

Searching / filtering programmes

from tvnow_epg import filter_by_channel, search_titles

# All programmes on one channel
news = filter_by_channel(schedule.programmes, "example.news")

# Case-insensitive substring search over titles
matches = search_titles(schedule.programmes, "ocean")

# Regular-expression search
import re
matches = search_titles(schedule.programmes, r"^The\b", regex=True)

Date/time filtering

from datetime import datetime, timezone
from tvnow_epg import filter_by_time

start = datetime(2024, 6, 10, 9, 0, tzinfo=timezone.utc)
stop  = datetime(2024, 6, 10, 13, 0, tzinfo=timezone.utc)

window = filter_by_time(schedule.programmes, start=start, stop=stop)

A programme is included when its air time intersects the [start, stop) window. Naive datetime objects are assumed to be UTC; use timezone-aware datetimes when your source feed uses a local offset.

Detecting schedule overlaps

from tvnow_epg import find_overlaps

for earlier, later in find_overlaps(schedule.programmes):
    print(f"{earlier.title} overlaps {later.title} on {earlier.channel_id}")

Overlaps are often a sign of malformed or stale guide data; this makes them easy to spot in validation tooling.

Normalizing metadata

from tvnow_epg import normalize_title, normalize_category

normalize_title("  The   News  ")   # "the news"
normalize_category("kids")          # "Children"
normalize_category("Film")          # "Movie"

JSON export

from tvnow_epg import to_json

text = to_json(schedule)                        # whole schedule
text = to_json(schedule, channel_id="example.news")  # one channel
text = to_json(schedule, indent=None)           # compact output

Timestamps are exported as ISO-8601 strings including their UTC offset.

Handling malformed data

The parser is lenient by design and suited to real-world EPG files:

  • Individual <channel> or <programme> elements that are missing an id, a valid start time, or a title are skipped rather than crashing.
  • Timestamps that cannot be parsed, or that lack an explicit UTC offset (in which case UTC is assumed), are handled deterministically.
  • A document that is not valid XML at all, or whose root element is not <tv>, raises tvnow_epg.ParseError (a ValueError subclass).

Testing

The test suite runs entirely offline:

pip install pytest
pytest

The bundled data/sample_epg.xml contains synthetic example data only — no real broadcaster's schedule.

Limitations

  • Supports the common core of the XMLTV format (channels, programmes, titles, descriptions, categories, episode numbers, ratings). Exotic extensions are ignored.
  • Timestamps without an explicit offset are assumed to be UTC.
  • The parser keeps the whole document in memory; very large multi-week guides (hundreds of MB) have not been a design target.
  • No network functionality of any kind is included.

This library is a data-format toolkit. It only processes schedule metadata that you supply. It does not access, locate, or provide media streams, and it does not circumvent any access controls. You are responsible for ensuring you have the right to use any EPG data you process with it, in line with the data provider's terms.

Additional TV schedule and EPG resources

  • XMLTV project — the format specification and associated tooling.
  • tvnow.live — an additional online TV schedule and EPG resource you can consult alongside this library.

License

MIT — see LICENSE.

Metadata

Release files for tvnow-epg 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tvnow-epg 0.1.0
File Size Uploaded Provenance
tvnow_epg-0.1.0.tar.gz 15.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tvnow-epg 0.1.0
File Interpreter ABI Platform
tvnow_epg-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.1 kB

Release files / tvnow_epg-0.1.0.tar.gz

Download URL tvnow_epg-0.1.0.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
56b0b89c207db8eff55baae7cc28779dfbbc578086cec69529b695170071fb82
BLAKE2b-256 checksum
How to use checksums
9ce7af48bb74a0dd95c38a3424608b6eeff59840a859f55d4ed6742be1238e14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / tvnow_epg-0.1.0-py3-none-any.whl

Download URL tvnow_epg-0.1.0-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2dc5f2b59a904ceec4049651de3df32a64508a7d28a5116ad174b9840b41d12
BLAKE2b-256 checksum
How to use checksums
8bd340dbb2ea2681577bc3be5df95176a2b89e1675db814efeac1b133d5b0d78
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for tvnow-epg 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page