Registry / serialization / gpxpy
library1.6.2pypypi✓ verified 84d ago

gpxpy is a Python library for parsing, manipulating, and creating GPX (GPS eXchange Format) files. GPX is an XML-based file format commonly used for GPS tracks, routes, and waypoints. The library supports both GPX 1.0 and 1.1 versions. It is currently at version 1.6.2 and is actively maintained, with regular releases and contributions.

pip install gpxpy
INSTALL
IMPORT
SIG · GPXPY
G
gpxpy
serializationpythonv1.6.2
Install
1.5s avg
Import
181ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v1.6.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.189s · 18.1MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.5s · import 0.172s · 19MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

gpxpy
import gpxpy
gpxpy.gpx
import gpxpy.gpx
from gpxpy import GPX, GPXTrack, GPXTrackSegment, GPXTrackPoint
While individual classes can be imported, `import gpxpy.gpx` is often used when creating new GPX objects for clarity.

This quickstart demonstrates how to parse an existing GPX file, iterate through its tracks, segments, and points, extract basic statistics, and programmatically create a new GPX structure with tracks and points. It also includes cleanup for the created dummy file.

import gpxpy import gpxpy.gpx import os # Create a dummy GPX file for demonstration dummy_gpx_content = """ <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <gpx xmlns="http://www.topografix.com/GPX/1/1" creator="gpxpy" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> <trk> <name>Example Track</name> <trkseg> <trkpt lat="48.123" lon="11.456"> <ele>500.0</ele> <time>2023-01-01T10:00:00Z</time> </trkpt> <trkpt lat="48.124" lon="11.457"> <ele>505.0</ele> <time>2023-01-01T10:01:00Z</time> </trkpt> </trkseg> </trk> <wpt lat="48.125" lon="11.458"> <name>Example Waypoint</name> </wpt> </gpx> """ dummy_gpx_filename = "example.gpx" with open(dummy_gpx_filename, "w") as f: f.write(dummy_gpx_content) try: # Parsing an existing GPX file with open(dummy_gpx_filename, 'r') as gpx_file: gpx = gpxpy.parse(gpx_file) print(f"GPX parsed successfully. Version: {gpx.version}") for track_idx, track in enumerate(gpx.tracks): print(f" Track {track_idx + 1}: {track.name or 'Unnamed Track'}") for segment_idx, segment in enumerate(track.segments): print(f" Segment {segment_idx + 1}: {len(segment.points)} points") for point_idx, point in enumerate(segment.points): print(f" Point {point_idx + 1}: Lat={point.latitude}, Lon={point.longitude}, Ele={point.elevation}, Time={point.time}") for wpt_idx, waypoint in enumerate(gpx.waypoints): print(f" Waypoint {wpt_idx + 1}: {waypoint.name or 'Unnamed Waypoint'} at Lat={waypoint.latitude}, Lon={waypoint.longitude}") # Getting some statistics if gpx.has_points(): moving_data = gpx.get_moving_data() print(f"Total distance: {gpx.length_3d()/1000:.2f} km") print(f"Max speed: {moving_data.max_speed * 3.6:.2f} km/h (filtered)") print(f"Total uphill: {gpx.get_uphill_downhill().uphill:.2f} m") print(f"Total downhill: {gpx.get_uphill_downhill().downhill:.2f} m") # Creating a new GPX file programmatically new_gpx = gpxpy.gpx.GPX() new_track = gpxpy.gpx.GPXTrack() new_gpx.tracks.append(new_track) new_segment = gpxpy.gpx.GPXTrackSegment() new_track.segments.append(new_segment) new_segment.points.append(gpxpy.gpx.GPXTrackPoint(48.2, 11.5, elevation=550, time='2023-01-01T11:00:00Z')) new_segment.points.append(gpxpy.gpx.GPXTrackPoint(48.21, 11.51, elevation=560, time='2023-01-01T11:05:00Z')) print("\nGenerated new GPX content:") print(new_gpx.to_xml()) finally: # Clean up the dummy file if os.path.exists(dummy_gpx_filename): os.remove(dummy_gpx_filename)
Debug
Known issues
gotchaThe `gpxpy.parse()` function expects a file-like object, not a file path string. Passing a path directly can lead to `xml.etree.ElementTree.ParseError: not well-formed (invalid token)` errors.
fix
Always open the GPX file first and pass the file object: `with open('your_file.gpx', 'r') as f: gpx = gpxpy.parse(f)`.
affects: All versions
gotchaThe `gpxpy` object model is not 100% equivalent to the GPX XML schema, particularly between GPX 1.0 and 1.1. Attributes like 'speed' (present in GPX 1.0 but removed in 1.1) might be lost or handled inconsistently if you parse one version and serialize to another without explicit management (e.g., using extensions or forcing version).
fix
Be aware of the GPX version when parsing and serializing. Use `gpx.to_xml(version='1.0')` or `gpx.to_xml(version='1.1')` to explicitly control the output version. For custom data, utilize GPX extensions.
affects: All versions
gotchaWhen calculating statistics like `max_speed` or `uphill/downhill`, `gpxpy` applies heuristics to filter out common GPS errors (e.g., removing top 5% of speeds or points with non-standard distances). The raw data might differ.
fix
If you need raw, unfiltered data for speed calculations, use `gpx.get_moving_data(raw=True)`. Understand that other statistical methods might also apply internal filtering.
affects: All versions
gotchaGPX extensions (custom XML elements within the GPX structure) are preserved as `ElementTree` DOM objects. However, they might be ignored when serializing a GPX 1.1 object to a GPX 1.0 file, and there have been reports of extension data being lost or not properly outputted during read/write operations if not handled carefully.
fix
When working with extensions, inspect the `gpx.extensions`, `point.extensions`, etc., to ensure data is retained as expected, especially after modification or serialization across different GPX versions. Test round-tripping for critical extension data.
affects: All versions
gotchaGenerated GPX XML, while always a valid XML document, may not always be a strictly valid GPX document if certain string fields (e.g., `gpx.email`) do not conform to the expected regex patterns defined by the GPX schema.
fix
Ensure that string inputs for GPX fields adhere to the GPX specification's format requirements if strict schema validation is required for target applications. Most applications are tolerant, but validation errors can occur.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'gpxpy'
The gpxpy library has not been installed in your current Python environment.
fix
pip install gpxpy
gpxpy.gpx.GPXException: Error parsing XML: not well-formed (invalid token): line X, column Y
The GPX file you are trying to parse is malformed, corrupted, or not a valid XML document according to GPX standards. This can also happen if the file is empty or contains unexpected characters at the beginning.
fix
Ensure the GPX file is a valid XML file. You might need to open it in a text editor to check for issues like an invalid root tag, unclosed tags, or extraneous characters, especially at the beginning of the file. If you are reading from a file path, ensure you pass a file object, not just the path string, to `gpxpy.parse()` if that's the expected input.
FileNotFoundError: [Errno 2] No such file or directory: 'your_file.gpx'
The specified GPX file does not exist at the given path, or the path is incorrect.
fix
Double-check the file name, its extension, and ensure it is in the correct directory. Provide an absolute path to the file or ensure your script's current working directory is where the file is located.
AttributeError: 'NoneType' object has no attribute 'offset'
This error typically occurs when trying to access the 'offset' attribute on a GPX point's time object, but the time object itself is None or has a timezone object that does not support 'offset', often due to naive (timezone-unaware) datetime objects or issues with specific timezone implementations within gpxpy's internal `SimpleTZ` class when interacting with other libraries like matplotlib.
fix
Before accessing attributes like 'offset' on a point's time, check if `point.time` is not `None`. For timezone-aware operations, consider converting `gpxpy`'s `datetime` objects to a standard timezone-aware format (e.g., using `pytz` or Python's `zoneinfo` module for Python 3.9+) before performing calculations or plotting. For example, `if point.time: # process point.time`.
point.speed returns None or AttributeError when accessing speed
The `speed` attribute was part of GPX 1.0 but was removed in GPX 1.1. If you are parsing a GPX 1.1 file, the `point.speed` attribute will be `None`.
fix
Check the GPX version of your file. If it's 1.1, the `speed` attribute is not directly available on `GPXTrackPoint` objects. You can calculate speed manually from consecutive points' time and position data using utility methods like `gpx.get_moving_data()` which calculates speed based on timestamps, or ensure you are working with GPX 1.0 if `speed` is critical.
Upgrade
Version history
1.6.2latest on PyPI · released Nov 29, 2023
Audit
Dependencies
lxmloptionalOptional dependency for faster XML parsing; if not present, minidom is used.
Agent activity
19 hits · last 30 days
node
16
Amazon
1
Resources