Configuration
gilguard has one setting: what to do when the GIL comes on. You set it with an environment variable or in code.
GILGUARD_ACTION
| Value | What happens |
|---|---|
raise (default) |
Raise GILEnabledError at the import that did it. |
warn |
Emit GILGuardWarning with the same report and keep running. |
off |
Don’t install the guard at all. |
GILGUARD_ACTION=warn python app.pyThe value isn’t case sensitive. Anything other than those three raises ValueError when gilguard is imported, so a typo fails fast instead of quietly turning the guard off.
When to use warn
warn suits a first pass over an existing app. You see every report in your logs without taking anything down, then switch to raise once the offenders are dealt with. The warning is a GILGuardWarning, a RuntimeWarning subclass, so your existing warning filters and logging capture it like any other.
Remember that in warn mode the program keeps running with the GIL on. It’s a way to find problems, not a way to live with them.
When to use off
off is for running the same code on a standard GIL build, where gilguard would otherwise raise because the GIL is always on. Set it in the environments that use a standard build and leave it unset where you run free-threaded.
In code
install() takes the same values and wins over the environment variable:
import gilguard
gilguard.install(action='warn')import gilguard already called install(), and a second call doesn’t add another hook. It just changes the action. If you need a specific action from the very first import, use the environment variable. Otherwise anything imported before your install() call runs under the default.
uninstall() removes the hook. Imports after that can turn the GIL on without a report. Call install() again to resume.
gilguard.uninstall()
import legacy_thing # unguarded
gilguard.install()PYTHON_GIL
CPython’s own PYTHON_GIL environment variable (or -X gil=) takes priority over everything above:
PYTHON_GIL=0keeps the GIL off no matter what gets imported. Nothing ever flips, so gilguard never fires. Use it only for extensions you’ve checked are thread-safe even though they don’t declare it.PYTHON_GIL=1forces the GIL on from the start. gilguard sees that when it’s imported and reports it as the cause.
Helpers
Two small functions are handy whether or not the guard is installed:
gilguard.is_free_threaded_build() # True on a 't' build
gilguard.gil_enabled() # True if the GIL is on right nowThey answer different questions. A free-threaded build can still have the GIL on, and that’s exactly the case gilguard exists for.