Equi7Grid icon indicating copy to clipboard operation
Equi7Grid copied to clipboard

avoid using pkg_resources to fetch version number

Open raphaelquast opened this issue 2 years ago • 6 comments

It seems that at the moment, 91% of the import-time for import equi7grid is due to the pkg_resources package whose only task is to identify the version number...

This performance penalty is well known for that package... I'd suggest using a different way to identify the version-number...

https://github.com/TUW-GEO/Equi7Grid/blob/c84b69bca84f19935ae808ac273bd2da29c8345e/equi7grid/init.py#L2-L7

here's a quick check of the relevant import-times:

raphaelquast avatar Jun 07 '22 15:06 raphaelquast

Thanks @raphaelquast ! May I assign you to this issue? I'll take care then of the release of the updated version.

bbauerma avatar Jun 13 '22 11:06 bbauerma

Hey, yep...it might take a bit till I find the time but I can implement the solution I'm using at the moment (e.g. basically suggestion 3 from here: https://packaging.python.org/en/latest/guides/single-sourcing-package-version/ )

  • create a separate "version.py" file containing just "__version__ = ..."
  • read the version-number from that file in both setup.py and __init__.py

raphaelquast avatar Jun 14 '22 09:06 raphaelquast

@raphaelquast would it help to generate project related files using pyscaffold? many of our python packages are based on it

sebhahn avatar Jun 14 '22 09:06 sebhahn

@sebhahn I don't have any experience with pyscaffold so far but from what I see they use setuptools_scm to do the job which is another way of circumventing the use of pkg_resources ... it's suggestion 7 from the link I posted earlier 😄 (it however adds a dependency on setuptools_scm but this is to 99% anyways already installed in any environment since a lot of packages are using it so I don't see any problem with that)

The way I'm doing it in EOmaps at the moment is a minimalistic (but native python) way:

https://github.com/raphaelquast/EOmaps/blob/51b4ffd55ec0a2abac0c8ada09d526293b69b87e/setup.py#L18-L23

and a simple from .version import __version__ in __init__.py

raphaelquast avatar Jun 14 '22 09:06 raphaelquast

my experience is that you install pyscaffold and run putup <projectname> and it generates an empty python project with some dummy files as well. there were some breaking changes in previous versions and at some point we need to update all our tuw-geo python packages that are using pyscaffold already to the latest version.

maybe we can start/test pyscaffold >4.0 and you can run your performance tests again?

sebhahn avatar Jun 14 '22 09:06 sebhahn

sure! I realized that import-performace tests are native and super easy in python>3.7 🙂 :

python -X importtime -c "import equi7grid" 2> import_time.log

and the visualization was done with tuna

tuna import_time.log

raphaelquast avatar Jun 14 '22 14:06 raphaelquast

I think this issue dies together with pyscaffold. I replaced all that stuff with a Makefile. Maybe @raphaelquast you want to test it again on your system, since I never really had this problem can can't reproduce t on mine it seems.

SwamyDev avatar Feb 13 '24 13:02 SwamyDev

a makefile and pyscaffold are two separate things

sebhahn avatar Feb 13 '24 14:02 sebhahn

I also don't get what the job of the make-file is in this context... (writing the version into _version.py)? (but yes, since pkg_resources is no longer required, I guess all should be fine)

The way I handle it now is to write the version-number directly into pyproject.toml and then parse it with the native importlib package, e.g.:

import importlib.metadata
__version__ = importlib.metadata.version("name of package")

raphaelquast avatar Feb 13 '24 14:02 raphaelquast

pyscaffold v4.5 writes this into the __init__.py:

import sys

if sys.version_info[:2] >= (3, 8):
    # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
    from importlib.metadata import PackageNotFoundError, version  # pragma: no cover
else:
    from importlib_metadata import PackageNotFoundError, version  # pragma: no cover

try:
    # Change here if project is renamed and does not equal the package name
    dist_name = __name__
    __version__ = version(dist_name)
except PackageNotFoundError:  # pragma: no cover
    __version__ = "unknown"
finally:
    del version, PackageNotFoundError

sebhahn avatar Feb 13 '24 15:02 sebhahn

nice, yep that's basically what I'm using as well (except for the additional python < 3.8 support)

raphaelquast avatar Feb 13 '24 15:02 raphaelquast

as pyscaffold and pkg_resource are not used anymore, I close the issue - thx!

bbauerma avatar Feb 13 '24 15:02 bbauerma