Python WeaselJsonParser constructor calls sys.exit(1) when the shared library is missing #38

Closed
opened 2026-06-28 23:13:00 +00:00 by weaselbot · 0 comments
Member

weaseljson.py terminates the whole interpreter with sys.exit(1) when it cannot load libweaseljson.so or libweaseljson.dylib. A library constructor should raise a normal exception so callers can handle the error gracefully.

Relevant code

File: weaseljson.py
Lines 88–94 (inside WeaselJsonParser.__init__):

        if self._lib is None:
            import sys

            print(
                "Could not find libweaseljson implementation",
                file=sys.stderr,
            )
            sys.exit(1)

Reproduction

import weaseljson

try:
    parser = weaseljson.WeaselJsonParser(
        weaseljson.WeaselJsonCallbacksBase(),
        build_dir="/nonexistent",
    )
except SystemExit as e:
    print(f"got SystemExit {e} instead of a normal exception")

Result:

Could not find libweaseljson implementation
got SystemExit 1 instead of a normal exception

Expected behavior

The constructor should raise an OSError (or RuntimeError) describing that the native library could not be loaded. Callers could then catch it and fall back to another parser, show a UI message, or skip the test.

Actual behavior

It calls sys.exit(1), which raises SystemExit and kills the Python process unless the caller explicitly catches SystemExit.

Impact

  • Applications that treat the parser as an optional dependency cannot fail gracefully.
  • Unit tests cannot use pytest.raises(OSError) or similar patterns; they must catch SystemExit or accept a crashed test runner.
  • The error message is printed to stderr, but the process exit code overrides any higher-level error handling.

The rest of the Python bindings already use exceptions for error reporting (e.g., ValueError when WeaselJsonParser_create returns NULL), so this path is inconsistent with the rest of the API.

`weaseljson.py` terminates the whole interpreter with `sys.exit(1)` when it cannot load `libweaseljson.so` or `libweaseljson.dylib`. A library constructor should raise a normal exception so callers can handle the error gracefully. **Relevant code** File: `weaseljson.py` Lines 88–94 (inside `WeaselJsonParser.__init__`): ```python if self._lib is None: import sys print( "Could not find libweaseljson implementation", file=sys.stderr, ) sys.exit(1) ``` **Reproduction** ```python import weaseljson try: parser = weaseljson.WeaselJsonParser( weaseljson.WeaselJsonCallbacksBase(), build_dir="/nonexistent", ) except SystemExit as e: print(f"got SystemExit {e} instead of a normal exception") ``` Result: ``` Could not find libweaseljson implementation got SystemExit 1 instead of a normal exception ``` **Expected behavior** The constructor should raise an `OSError` (or `RuntimeError`) describing that the native library could not be loaded. Callers could then catch it and fall back to another parser, show a UI message, or skip the test. **Actual behavior** It calls `sys.exit(1)`, which raises `SystemExit` and kills the Python process unless the caller explicitly catches `SystemExit`. **Impact** - Applications that treat the parser as an optional dependency cannot fail gracefully. - Unit tests cannot use `pytest.raises(OSError)` or similar patterns; they must catch `SystemExit` or accept a crashed test runner. - The error message is printed to stderr, but the process exit code overrides any higher-level error handling. The rest of the Python bindings already use exceptions for error reporting (e.g., `ValueError` when `WeaselJsonParser_create` returns `NULL`), so this path is inconsistent with the rest of the API.
weaselbot was assigned by andrew 2026-06-29 17:33:22 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/weaseljson#38