hgrecco / pint

Operate and manipulate physical quantities in Python
http://pint.readthedocs.org/
Other
2.41k stars 473 forks source link

Default Unit registry initialization is not thread safe #2039

Open Czaki opened 4 months ago

Czaki commented 4 months ago

For performance of init, the default registry is created using LazyRegistry

https://github.com/hgrecco/pint/blob/5f2a76a42c44f0077908be212c5445a657da639a/pint/__init__.py#L50C1-L50C18

However, the code for load and initialize register

https://github.com/hgrecco/pint/blob/5f2a76a42c44f0077908be212c5445a657da639a/pint/registry.py#L187-L192

is not thread safe, so if two threads try to access to registry it may end with exception like:

  File "napari/utils/transforms/transforms.py", line 477, in __init__
    self._units = (pint.get_application_registry().pixel,) * ndim
  File "pint/registry.py", line 251, in __getattr__
    return getattr(self._registry, name)
  File "pint/facets/plain/registry.py", line 367, in __getattr__
    return self.Unit(item)
  File "pint/facets/plain/unit.py", line 41, in __init__
    self._units = self._REGISTRY.parse_units(units)._units
  File "pint/facets/plain/registry.py", line 1199, in parse_units
    self.parse_units_as_container(input_string, as_delta, case_sensitive)
  File "pint/facets/nonmultiplicative/registry.py", line 69, in parse_units_as_container
    return super().parse_units_as_container(input_string, as_delta, case_sensitive)
  File "pint/facets/plain/registry.py", line 1214, in parse_units_as_container
    return self._parse_units_as_container(input_string, as_delta, case_sensitive)
  File "pint/facets/plain/registry.py", line 1249, in _parse_units_as_container
    cname = self.get_name(name, case_sensitive=case_sensitive)
  File "pint/facets/plain/registry.py", line 658, in get_name
    raise UndefinedUnitError(name_or_alias)

There should be at least information in get_application_registry doc string about this problem or initialization of register should be protected using proper objects from threading library, for example Lock.

I may try to implement such a thing if you wish.