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>, raisestvnow_epg.ParseError(aValueErrorsubclass).
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.
Legal / usage considerations
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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tvnow_epg-0.1.0.tar.gz | 15.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.