pyephem exposes XEphem's astronomy routines as the ephem Python package
Scientific-grade astronomy routines for Python
At a glance
- What is it?
- PyEphem is a Python package for high-precision astronomy computations whose numeric core is the C code behind the XEphem application, used with the author's permission. Installation is a single pip command if you have a C compiler, the API is object oriented with values that print themselves in astronomical format, and the repository still builds its lunar data tables through a Makefile driven generator.
- Who is it for?
- Adopt PyEphem if you need astronomical positions, rise, transit and set times, Moon phases or coordinate conversions in Python and you would rather call vetted C routines than implement the ephemerides yourself. Do not adopt it if you need a pure Python install with no compiler available, since the package is a C extension, and do not treat it as a replacement for a full planetarium package with its own catalogue and display layer.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The C astronomy code is XEphem's, reused with permission
PyEphem provides an ephem Python package for performing high-precision astronomy computations, and the important sentence in the README is the second one. The underlying numeric routines are coded in C and are the same ones that drive the popular XEphem astronomy application, whose author, Elwood Charles Downey, generously gave permission for their use in PyEphem.
That provenance is the whole value proposition. Writing an accurate ephemeris is not a weekend project. The theory of planetary motion, the perturbations, the precession and nutation of the reference frame, the lunar theory, the atmospheric refraction model, all of it has to be right to the arcminute or the answers are not useful. XEphem is an established application whose routines the README presents as proven, and PyEphem is a Python binding onto that work rather than a reimplementation.
The README also explains the name. The name ephem is short for the word ephemeris, which is the traditional term for a table giving the position of a planet, asteroid or comet for a series of dates. The package is called ephem even though the project is called PyEphem, and that distinction trips people up when they search for it.
The audience is Python programmers who need astronomy numbers rather than a planetarium: someone computing observing windows for a telescope, plotting satellite passes, working out where a body will be at a given instant, or writing an almanac. The design emphasis stated in the README is on convenience and ease of use, and that shows up in the API shape rather than in the internals.
Installation needs a C compiler, and the pip command is ephem
The install story is short, with one condition attached. If you have a C compiler and the pip installer on your system, then installing PyEphem should be as easy as:
pip install ephemNote the package name. The distribution is ephem, not pyephem, and the import is also ephem. The README links the PyPI pages for both, the ephem package and the pyephem package, so both spellings exist somewhere in the distribution history, but the pip command in the README installs ephem.
There are also Windows installers in the downloads section of the project site, which matters because the C compiler requirement is the main friction point for a Windows user without a build environment.
For a developer who wants to read the source, the README gives a static copy link as well as the GitHub repository, and describes how to run the source in place. You create a virtual environment, activate it, change to the root of the source tree, and run:
python setup.py build_ext -iThat builds the extension module in place so the tree can be imported without installing it. The test suite then runs with:
python -m unittest discover ephemThe README frames that as a way to see whether all of its features are working correctly on your operating system and platform, which is the right way to think about it. A C extension with floating point behaviour, and with a maths library dependency, is exactly the kind of thing that behaves differently across platforms, and the test suite is the check.
Objects compute, and the values print themselves in astronomical format
The design is object oriented in a way that removes most of the work from the caller, and the README shows it in five lines:
>>> import ephem
>>> mars = ephem.Mars()
>>> mars.compute('2008/1/1')
>>> print(mars.ra)
5:59:27.35
>>> print(mars.dec)
26:56:27.4Two things are happening there. The first is that a body is an object, so mars is a Mars instance rather than a function call with a date argument. The second is that compute takes a date string and mutates the object, and the attributes then hold the results for that instant.
The printed values are the other half of the design. Both celestial bodies and the observer's location on Earth are represented by Python objects, while dates and angles automatically print themselves in standard astronomical formats. The right ascension comes out as hours, minutes and seconds, and the declination as degrees, arcminutes and arcseconds, without any conversion call in the user code. A library that made the user convert a float into sexagesimal by hand every time would be less pleasant in exactly the situation astronomy code lives in.
The observer is an object too, which is what makes the local horizon part of the API rather than an afterthought. You supply longitude, latitude and altitude of the location you are observing from, and PyEphem uses that in the rise, transit and set calculations and in the refraction correction. For convenience a small database of longitudes and latitudes for 122 world cities is included, so the common case does not require you to look up a coordinate.
The refraction model is the detail worth noting. For specified weather conditions, temperature and pressure, PyEphem compensates for atmospheric refraction by adjusting the positions of bodies near the horizon. Refraction matters most exactly where observation happens, at the horizon, and a library that lets you feed in the actual conditions is doing more than the usual fixed model.
What the package actually covers
The feature list in the README is a good map of the capability, and it is broader than planet positions.
Finding where a body is in the sky comes first. High-precision orbital routines are provided for the Moon, the Sun, the planets and the major planet moons. The user can supply the orbital elements of a comet, asteroid or Earth-orbiting satellite and have its location computed, and the positions of 94 bright stars come built in, with the ability to create further fixed objects as needed for your own calculations.
Determining where an object appears for a particular observer is the second group, and that is the longitude, latitude and altitude input described above, the city database, and the refraction compensation.
Then there is the time domain. PyEphem computes when a body will rise, transit overhead and set from a particular location. It determines the dates of the equinoxes and solstices, and computes the dates of the various phases of the Moon. It converts from the Greenwich Time, more precisely Ephemeris Time, which PyEphem uses, to the local time of the user.
Two more capabilities are worth calling out because they are less common. The package can parse and use orbital data in either the traditional XEphem file format or the standard TLE format used for tracking Earth-orbiting satellites, so satellite data from elsewhere can be fed in. And it can determine on which page of the Uranometria or the Millennium Star Atlas a particular star should appear, which is a genuinely niche and very specific feature.
The package also returns the Julian Date corresponding to any calendar date, and can convert positions between the equatorial, ecliptic and galactic coordinate systems.
Taken together, this is a fairly complete ephemeris toolkit with the observation oriented parts included, which is more than most astronomy code needs and about what a scientific Python user would want to avoid writing.
The extension is C files from libastro, plus data tables compiled into C
The setup.py file explains how the package is assembled, and the mechanism is the interesting part for anyone who needs to rebuild it or understand its footprint.
The version is read out of the module source itself, by scanning ephem/__init__.py for the line that starts with __version__ and evaluating it, so there is one place where the version is defined. The C sources are then collected with two globs:
libastro_files = glob('libastro/*.c')
libastro_data = glob('extensions/data/*.c')So the extension is built from every C file in the libastro directory, which is the XEphem numerical core, plus every generated C file in the extensions/data directory, which holds the data tables, plus the two hand written extension files for the module and the floating point formatting helper.
The compile flags are worth a note. extra_compile_args sets -ffloat-store, which changes how the compiler handles floating point values in memory. That is a deliberate numerical choice in a library whose output is angles, and it is the kind of flag you should not casually remove when rebuilding.
Libraries are handled with a platform check. On anything that is not Windows, the maths library is added to the link line, with a comment recording that linking against the library named m on Windows produces the error cannot open input file m.lib, and a second note that it is needed for Android, referring to a GitHub issue.
The result is a single extension module named ephem._libastro, and the pure Python ephem package sits on top of it. That split is why the package is described as scientific grade rather than approximate, and also why a compiler is a hard requirement rather than an optional accelerator.
The lunar data tables are regenerated by a Makefile rule
The Makefile at the root is short and it is about data rather than code, which tells you something about the maintenance model of this project.
D=./data
E=./extensions/data
BDLS=$(patsubst $D/%, %, $(wildcard $D/*.9910 $D/*.1020 $D/*.2040))
BDLSRCS=$(patsubst %, $E/%.c, $(BDLS))The variable names are abbreviated to the point of being cryptic, and it takes a moment to read. The data directory holds source data files with three extensions, .9910, .1020 and .2040, which are the standard names for the lunar theory data files, and the wildcard collects them. The patsubst then maps each one to a C source path under the extensions/data directory, which is where the compiled tables live.
The rule that does the work is:
$(BDLSRCS): $E/%.c: $D/% bin/rebuild-plmoon-data
bin/rebuild-plmoon-data $D/$* > $@A script called bin/rebuild-plmoon-data reads the data file and writes a C file, and the output is redirected into the target. The dependency chain is explicit, so make rebuilds the C tables when the data changes and skips them when it does not.
The reason this matters is that the data files and the compiled C tables are both in the repository, and the two directories are the data/ directory and the extensions/data directory. The upstream data comes from the lunar theory tables, so when those are updated the tables have to be regenerated and the generated C committed, otherwise the build and the published data drift apart.
The top level also has a CMakeLists.txt, a setup.py and a Makefile, so the project supports both a Python packaging build and a native CMake build, and a data/ directory alongside libastro/ for the source data.
Licence, documentation build and the maintenance picture
Two things about the licence are worth flagging, because they do not obviously agree. The setup.py file records license = 'MIT' and the author as Brandon Rhodes, while the licence field on the repository itself records a custom licence that GitHub cannot classify, with a pointer to the LICENSE file at the root. The LICENSE file is what governs, and it is worth reading rather than assuming the MIT marker in the manifest is the whole story.
The documentation is a Sphinx project, and the README gives both ways to build it. The command line form is:
sphinx-build -b html pyephem/ephem/doc/ ./my_documentation_directory/and the more typical route is a target in the documentation's own Makefile:
make -C ephem/doc htmlThe requirements file pins the documentation toolchain tightly, with docutils 0.17.1 and sphinx 1.7.6. Those are old pins, and they are the reason the documentation build may not work with a current Python environment. That is a real observation for anyone trying to rebuild the docs today.
User facing documentation is also distributed inside the package. The README says the Quick Reference and the Tutorial are included as text files within the module itself, as well as being available on the project website, which is a sensible arrangement for a package that people install without reading the site.
On maintenance, the repository is not archived and the last push was on 2026-10-16, so work continues. There are no GitHub releases, so the version history lives in the package itself rather than in tags. The site also hosts a bug tracker, a user support forum and the source repository, and the README is explicit that a static copy of the most recent source can be downloaded as a zip for anyone who does not want to use version control.
Editorial conclusion
Adopt PyEphem if you need astronomical positions, rise, transit and set times, Moon phases or coordinate conversions in Python and you would rather call vetted C routines than implement the ephemerides yourself. Do not adopt it if you need a pure Python install with no compiler available, since the package is a C extension, and do not treat it as a replacement for a full planetarium package with its own catalogue and display layer. Before you install, confirm you have a C compiler and, on a non Windows machine, the maths library the extension links against, and check the licence position yourself, because the package manifest records MIT while the licence field on the repository records a custom licence that GitHub cannot classify.
Frequently asked questions
How do I install PyEphem?
With pip install ephem, provided you have a C compiler and the pip installer on your system, since the package is a C extension. There are also Windows installers in the downloads section of the project site.
What astronomy can the ephem package compute?
Positions of the Moon, Sun, planets and major planet moons, rise, transit and set times for an observer location, equinox and solstice dates, Moon phases, coordinate conversions between equatorial, ecliptic and galactic systems, and parsing of both XEphem format and TLE orbital data.
Where do the ephemeris routines come from?
The numeric routines are coded in C and are the same ones that drive the XEphem astronomy application, whose author Elwood Charles Downey gave permission for their use in PyEphem. The extension is built from the C files in the libastro directory.
How do I build PyEphem from source and run its tests?
Create a virtual environment, activate it, change to the root of the source tree and run python setup.py build_ext -i, which builds the extension in place. The test suite is then run with python -m unittest discover ephem.
What licence does PyEphem use?
The setup.py manifest records license = 'MIT', while the licence field on the repository records a custom licence that GitHub cannot classify, with the terms in the LICENSE file at the repository root. Check that file for the position that applies to your use.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/brandon-rhodes-pyephem)Was this useful?