Exceptions¶
See Handling errors for the guide.
thresher.exceptions ¶
The exceptions this package raises, and the wording they carry.
Everything raised from thresher derives from ThresherError, so a caller can catch this
package's failures without also catching unrelated ones:
try:
Thresher().optimize_threshold(scores, actual_classes)
except thresher.exceptions.InvalidInputError as exc:
...
Each class also inherits the builtin it used to be raised as - ValueError,
TypeError, AttributeError, ImportError, NotImplementedError. That is deliberate
rather than decorative: code written against any earlier version catches those builtins,
and this package's own command line catches ValueError and ImportError. Dual
inheritance makes the hierarchy an addition rather than a breaking change.
Where an error carries useful detail - how many scores, which labels, what was available - it is kept on the instance as well as formatted into the message, so callers can act on it instead of parsing prose.
The message templates stay as module constants. They define the wording, tests assert against the same strings the user sees, and they were importable before the classes existed.
ThresherError ¶
Bases: Exception
Base class for every error raised by this package.
Catch this to handle anything thresher rejects, without also catching failures from numpy, pandas or your own code that happen to use the same builtin types.
ConfigurationError ¶
Bases: ThresherError, ValueError
Something was asked for that does not exist - a mistyped name, usually.
Raised while an object is being built, before any data is touched.
UnknownAlgorithmError ¶
Bases: ConfigurationError
No algorithm goes by that name, or any of its synonyms.
Record what was asked for and what would have worked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
Any
|
the name that matched nothing. Usually a mistyped string, but anything arrives here - a non-string is as unknown as a wrong spelling. |
required |
available
|
Iterable[str]
|
the algorithm ids that would have. |
required |
Source code in src/thresher/exceptions.py
UnknownBackendError ¶
Bases: ConfigurationError
No execution backend goes by that name.
Record what was asked for and what would have worked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
Any
|
the name that matched nothing. |
required |
available
|
Iterable[str]
|
the backend names that would have. |
required |
Source code in src/thresher/exceptions.py
InvalidInputError ¶
Bases: ThresherError, ValueError
The data cannot be optimized over as given.
EmptyInputError ¶
LengthMismatchError ¶
Bases: InvalidInputError
The scores and the classes do not line up one to one.
Record both counts, so a caller can report or repair the difference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score_count
|
int
|
how many scores were given. |
required |
class_count
|
int
|
how many classes were given. |
required |
Source code in src/thresher/exceptions.py
MissingLabelsError ¶
Bases: InvalidInputError
Some scores have no class at all - a blank cell arrives as NaN.
Record how many are missing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
int
|
number of missing values found. |
required |
Source code in src/thresher/exceptions.py
UndefinedScoresError ¶
Bases: InvalidInputError
Some scores are NaN, so no threshold can be placed relative to them.
Distinct from MissingLabelsError, which is the same problem on the other column.
Before 0.7.1 this went unchecked and each algorithm failed its own way: exact
returned NaN as though it were an answer - a threshold that classifies everything
negative, since every comparison against NaN is false - while hist raised a bare
ValueError from its bin arithmetic.
Record how many are undefined.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
count
|
int
|
number of NaN scores found. |
required |
Source code in src/thresher/exceptions.py
UnexpectedLabelsError ¶
Bases: InvalidInputError
Labels outside the -1 / 1 pair the solvers work in.
Record the offending values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unexpected
|
Iterable[Any]
|
the label values that are neither -1 nor 1. |
required |
Source code in src/thresher/exceptions.py
SingleClassError ¶
Bases: InvalidInputError
Only one of the two classes is present, so there is nothing to separate.
Record the class that was found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
only
|
Any
|
the single label value present. |
required |
Source code in src/thresher/exceptions.py
InsufficientDataError ¶
Bases: InvalidInputError
Too little data for this algorithm to produce a candidate threshold.
LabelMappingError ¶
Bases: ThresherError, TypeError
The labels option cannot map the classes it was given.
NotIterableError ¶
Bases: ThresherError, AttributeError
scores or actual_classes is not something that can be iterated.
Inherits AttributeError because that is what earlier versions raised. TypeError
would fit the failure better, but changing it would break existing except clauses
for no practical gain.
Record which argument was not iterable, and name it in the message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attribute
|
str
|
the offending argument - |
'scores'
|
Source code in src/thresher/exceptions.py
BackendDependencyError ¶
Bases: ThresherError, ImportError
A backend was selected whose optional dependency is not installed.
ParallelBootstrapError ¶
Bases: ThresherError, RuntimeError
Worker processes could not be started, so the work never ran.
Inherits RuntimeError because that is what BrokenProcessPool - the failure this
replaces - already was, so an except RuntimeError written around a parallel run keeps
working. Before 0.7.0 this situation had no exception at all: multiprocessing.Pool
waited on workers that would never report, and the process simply hung.
AlgorithmNotWiredError ¶
Bases: ThresherError, NotImplementedError
An algorithm is in the registry but has no branch in the dispatcher.
A mistake in the package rather than in the caller's code: it means
available_algorithms and run_computations have drifted apart.
Source code in src/thresher/exceptions.py
ShardMergeError ¶
Bases: ThresherError, ValueError
Partial results from a distributed run could not be combined.
Also a package-level mistake rather than a caller's: the shards disagree about how many candidates were scored, which cannot happen within a single run.