Setting Python's Decimal Context for All Threads2020-03-23
Python’s decimal module has concept of a “context.”
This defines the default precision of new
Decimals, how rounding works, and lots of other behaviour.
Maths gets complicated!
It’s quite common to need to customize the decimal context, to control one of these features. As the decimal documentation states, contexts are per-thread:
getcontext()function accesses a different Context object for each thread. Having separate thread contexts means that threads may make changes (such as
getcontext().prec=10) without interfering with other threads.
This isolation is good, but it also means that it’s an easily forgotten concern when adding threading. This could cause hard-to-discover arithmetic bugs. Oh no!
Thankfully, there’s a fix, as per the decimal documentation:
[For new threads] the new context is copied from a prototype context called
DefaultContext. To control the defaults so that each thread will use the same values throughout the application, directly modify the
DefaultContextobject. This should be done before any threads are started so that there won’t be a race condition between threads calling
It then has this example:
This is great but it requires us to think through how we’d specify this context. What if you want to use one of the pre-defined contexts?
For example there’s
It’s pretty useful, as it’s a standard:
This is a standard context defined by the General Decimal Arithmetic Specification.
Here’s an adaptation of the previous example to pull all attributes from
inspect.signature() to find all the parameters a
The previous snippet listed them all explicitly:
Using inspection instead means that our code is robust to future expansions in the
In Django you can store
Decimal values with
DecimalField database field.
If you use it, you probably want to use this same context-setting technique.
The best place to do so is inside an
This runs at project startup.
It’s possible your other apps or third party packages start threads at startup, so you should check if they do.
You can do so by adding a
If you find other threads, you can try setting the context earlier.
You can do this by pushing your app to the top of
If that still doesn’t work, you could try moving the snippet to your settings file.
Hope this helps you control your decimal arithmetic,
Are your Django project's tests slow? Read Speed Up Your Django Tests now!
One summary email a week, no spam, I pinky promise.
© 2020 All rights reserved.