ly-to-musicxml
Compiler-assisted conversion from LilyPond .ly files to MusicXML 4.0.
This project has been manually validated both from the local source tree and from an installed TestPyPI package.
Approach
This converter does not statically parse LilyPond source and it does not use PDF or optical music recognition.
It runs LilyPond itself in a no-print extraction mode, lets LilyPond resolve \include files and embedded Scheme, exports LilyPond's internal music tree to XML, then translates that compiler-resolved XML into MusicXML.
Normal conversion does not generate PDF output.
Installation
Install the project in editable mode:
pip install -e .
For packaging, testing, and documentation tasks, use a standard CPython install or a normal virtual environment. Avoid using LilyPond's bundled Python as your main project interpreter because it does not include normal packaging tooling such as pip, build, or twine.
You can also run it without installation:
$env:PYTHONPATH = (Resolve-Path .\src)
python -m ly_to_musicxml "input.ly" -o "output.musicxml"
Install from PyPI once published:
pip install ly-to-musicxml
This package depends on an external LilyPond installation at runtime. Installing with pip only installs the Python package and CLI; it does not install LilyPond itself.
Requirements
- Python 3.10 or newer
- A working LilyPond installation available either through
--lilypond-bin,LY_TO_MUSICXML_LILYPOND_BIN, or the default configured path
The converter executes LilyPond during every run, so a missing or incompatible LilyPond install is the most common setup problem.
Usage
ly-to-musicxml "input.ly" -o "output.musicxml"
If -o is omitted, the converter writes the first output file next to the input using the same stem and a .musicxml extension.
LilyPond Binary Selection
The converter looks for LilyPond in this order:
--lilypond-binLY_TO_MUSICXML_LILYPOND_BIN- The reference path from the project brief:
C:\Users\kkris\Documents\lilypond-2.26.0-mingw-x86_64\lilypond-2.26.0\bin\lilypond.exe
Example:
ly-to-musicxml "input.ly" -o "output.musicxml" --lilypond-bin "C:\path\to\lilypond.exe"
Or via environment variable:
$env:LY_TO_MUSICXML_LILYPOND_BIN = "C:\path\to\lilypond.exe"
ly-to-musicxml "input.ly" -o "output.musicxml"
Multi-Score Inputs
If the input produces multiple non-empty scores or books, the converter preserves them by writing multiple MusicXML files.
- The first non-empty score is written to the requested output path.
- Additional non-empty scores are written into a sibling directory named
stem.exports/using the patternbook-NN-score-NN.musicxml. - Empty scores are skipped with warnings.
If you rerun the converter for the same output path, it clears the previous stem.exports/ directory and any legacy stem.bookNN.scoreNN.musicxml files before writing fresh outputs.
Example output layout for a multi-score input:
Shostakovich-String-Quartet-8.musicxml
Shostakovich-String-Quartet-8.exports/
book-01-score-02.musicxml
book-02-score-01.musicxml
...
What Is Currently Mapped
The current translator maps these runtime LilyPond constructs to MusicXML:
- Parts and staves
- Notes, rests, chords, tuplets, and unfolded repeats
- Key signatures, time signatures, pickups, and barlines
- Ties, slurs, dynamics, text directions, tempo marks, and wedges
- Breath marks, ottava shifts, fermatas, and common articulation/bowing marks
Scheme Handling
If the source file contains embedded Scheme syntax, the converter emits a warning that the output reflects one compiler evaluation. This is intentional: the converter uses the actual LilyPond runtime result instead of guessing what the Scheme might do.
Troubleshooting
If the CLI reports that it cannot find LilyPond:
$env:LY_TO_MUSICXML_LILYPOND_BIN = "C:\path\to\lilypond.exe"
ly-to-musicxml "input.ly" -o "output.musicxml"
If a conversion writes multiple files unexpectedly, check for a sibling stem.exports/ directory next to the main output file. That directory contains additional non-empty scores extracted from the same LilyPond input.
If the output looks wrong in another notation program, first confirm you are opening the newly generated .musicxml file rather than an older export from a previous run.
If VS Code auto-selects LilyPond's bundled Python for this workspace, switch to a standard CPython interpreter or a normal venv before doing package builds, pip install, or twine upload. The bundled interpreter can run LilyPond internals but is not a good development environment for this project.
Test
Run the focused regression test with:
python -m unittest tests.test_converter
Manual smoke tests used during validation:
$env:PYTHONPATH = (Resolve-Path .\src)
python -m ly_to_musicxml --help
python -m ly_to_musicxml "Shostakovich-String-Quartet-8.ly" -o "local-manual-smoke.musicxml" --lilypond-bin "C:\Users\kkris\Documents\lilypond-2.26.0-mingw-x86_64\lilypond-2.26.0\bin\lilypond.exe"
TestPyPI smoke test after publishing:
py -3.13 -m venv .testpypi-venv
.\.testpypi-venv\Scripts\python.exe -m pip install --upgrade pip
.\.testpypi-venv\Scripts\python.exe -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple ly-to-musicxml
.\.testpypi-venv\Scripts\ly-to-musicxml.exe "Shostakovich-String-Quartet-8.ly" -o "testpypi-smoke.musicxml" --lilypond-bin "C:\Users\kkris\Documents\lilypond-2.26.0-mingw-x86_64\lilypond-2.26.0\bin\lilypond.exe"
Metadata
Release files for ly-to-musicxml 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ly_to_musicxml-0.1.1.tar.gz | 18.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ly_to_musicxml-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 39.5 kB
Release files / ly_to_musicxml-0.1.1.tar.gz
| Download URL | ly_to_musicxml-0.1.1.tar.gz |
|---|---|
| Size | 18.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8ca3bc5286ad8e8cf130ccb9c7bb09d3147273aa9cf8da1f5bdf6a9f63311e4c
|
|
BLAKE2b-256 checksum How to use checksums |
a4da05255e67cbc3db5fffc4a8f2d9f8a934296c1b7ae4191adee0cd4d5d5a4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 2, 2026.
Transparency logRelease files / ly_to_musicxml-0.1.1-py3-none-any.whl
| Download URL | ly_to_musicxml-0.1.1-py3-none-any.whl |
|---|---|
| Size | 21.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
be14f4194e38f48d7f540615ee85a5a69ded84cb9df72713e7b74c67ab593417
|
|
BLAKE2b-256 checksum How to use checksums |
4f91bb9d8f2e75dbbe15e031ba82700563453d124a983ef0a202d8b947106a4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 2, 2026.
Transparency log