Skip to main content

python-ntpdshm

Overview

python-ntpdshm provides a Python interface to ntpd’s shared memory driver 28. A single class NtpdShm exposes the fields of the shared memory structure as attributes that can be read and written. In addition there are properties to set the clock and receive timestamps from float values. There is also a convenience update() function for setting the time related fields in a single step.

python-ntpdshm is implemented using Swig.

python-ntpdshm works with the following Python versions.

  • Python 2.6

  • Python 2.7

  • Python 3.3

  • Python 3.4

  • Python 3.5

  • PyPy (but not PyPy3!)

Example

import ntpdshm

ntpd_shm = ntpdshm.NtpdShm(unit=0)

The members of the C struct can be accessed by their original names. These have not been converted into PEP-8 compliant names.

print ntpd_shm.mode
print ntpd_shm.clockTimeStampSec
print ntpd_shm.clockTimeStampUSec
print ntpd_shm.clockTimeStampNSec      # only ntpd 4.2.7p303 or later, probably random value otherwise
print ntpd_shm.receiveTimeStampSec
print ntpd_shm.receiveTimeStampUSec
print ntpd_shm.receiveTimeStampNSec    # only ntpd 4.2.7p303 or later, probably random value otherwise
print ntpd_shm.leap
print ntpd_shm.precision
print ntpd_shm.valid

In addition there are two pseudo properties that combine the second and microsecond attributes into “float” timestamps. These don’t support nanosecond precision as (as far as I know) it is not possible to detect whether ntpd does support nanosecond resolution.

print ntpd_shm.clockTimeStamp          # clockTimeStampSec.clockTimeStampUSec
print ntpd_shm.receiveTimeStamp        # receiveTimeStampSec.receiveTimeStampUSec

The process to feed ntpd an external reference time is shown below.

import time

clock_time = get_clock_time()          # `get_clock_time` must be implemented somewhere else and
                                       # return a float.
recev_time = time.time()
ntpd_shm.valid = 0                     # don't use Python boolean
ntpd_shm.clockTimeStamp = clock_time
ntpd_shm.receiveTimeStamp = recv_time
ntpd_shm.precision = -5                # 2^-5 = 0.03125 seconds in this case
ntpd_shm.count += 1
ntpd_shm.valid = 1

As this is somewhat cumbersome, there is a convenience method update() that achieves the same in a single line. It requires the clock_time as mandatory argument and accepts several optional arguments.

ntpd_shm.update(clock_time, recv_time=recv_time, precision=-5)

# Or simply, if no other fields are to be changed. The receive timestamp is set
# automatically.
ntpd_shm.update(clock_time)

Applications

“Off by one second” reference time

A just for fun example of using python-ntpdshm is to implement an “off by one second” reference time source for ntpd. While this example makes no sense at all for practical purposes it provides a useful template for how it all fits together.

First we write the code for the reference clock.

import time
import ntpdshm

def get_clock_time():
    return time.time() - 1.0     # always be exactly one second behind.

def main():
    ntpd_shm = ntpdshm.NtpdShm(unit=2)
    ntpd_shm.mode = 0            # set mode
    ntpd_shm.precision = -6      # set precision once
    ntpd_shm.leap = 0            # how would we know about leap seconds?

    while True:
        clock_time = get_clock_time()
        ntpd_shm.update(clock_time)
        time.sleep(1.0)

if __name__ == '__main__':
    main()

Then add the shared memory reference clock to ntp.conf:

# ntp.conf
...
server 127.127.28.2 noselect     # unit=2, never select this reference
fudge 127.127.28.2 refid PYTH stratum 10

Restart ntpd and monitor the output of ntpq -pn. The offset should be exactly -1000 msec:

$ ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
...
 127.127.28.2    .PYTH.          10 l    9   16  377    0.000  -1000.0   0.017

History

0.1.0 (15-Dec-2015)

  • Initial version

Metadata

Release files for ntpdshm 0.2.1

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

Source distribution (sdist)

Source distribution for ntpdshm 0.2.1
File Size Uploaded Provenance Actions
ntpdshm-0.2.1.tar.gz 42.3 kB Without provenance Details for ntpdshm-0.2.1.tar.gz

Release files / ntpdshm-0.2.1.tar.gz

Download URL ntpdshm-0.2.1.tar.gz
Size 42.3 kB
Tags Source
SHA-256 checksum
How to use checksums
b8c51773ea03789a1697e124b01a43ca4e0e77f2bacdd6858bccfb0b174309e2
BLAKE2b-256 checksum
How to use checksums
41b3eca2a32f63252b5fb95898200a99fb4af1a5fc6559ebbd35e35bd29e2bf6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for ntpdshm 0.2.1

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.2.1 This release

1 release file 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