Search code examples
python-importpython-packagingpython-poetrypython-importlib

How do I embed the version from pyproject.toml so my package can use it?


The version in my project is stored in pyproject.toml:


[tool.poetry]
name = "package_name"
version = "1.2.3"
# ...

I now want to have a __version__ in package_name/__init__.py as well and the general suggestion seems to be:

import importlib_metadata

__version__ = importlib_metadata.version('package_name')

But that doesn't work for me. The moment I run my unittests I get this error:

importlib_metadata.PackageNotFoundError: No package metadata was found for package_name

How can I make this work during development?


Solution

  • Having a __version__ attribute in the import package (i.e. in package_name/__init__.py) is an outdated practice. The current best practice is to rely on the distribution package's metadata with the help of importlib.metadata from Python's standard library.

    So for example if in my application I want to get the version string for your library, instead of writing this in my application:

    import package_name  # Your library's "import package" name
    
    version = package_name.__version__
    

    I would write this:

    import importlib.metadata
    
    lib_name = "package_name"  # Your library's "distribution package" name 
    lib_version = importlib.metadata.version(lib_name)
    

    For this to work I need to be sure that your library package_name is correctly installed.


    Now if in my application I want to show my application's own version string, it is the same principle:

    import importlib.metadata
    
    app_name = "my-app-name"  # My app's "distribution package" name 
    app_version = importlib.metadata.version(app_name)
    
    lib_name = "package_name"  # Your library's "distribution package" name 
    lib_version = importlib.metadata.version(lib_name)
    
    print(f"This is {app_name} version {app_version}, it uses {lib_name} version {lib_version}.")
    

    As mentioned earlier I have to make sure that all the distribution packages (application and libraries) are correctly installed. So-called "editable" installations are perfectly fine.

    If my application is managed by Poetry, then Poetry installs my application as editable anyway. The important thing to keep in mind is that it is necessary to re-install after every modification in the relevant parts of pyproject.toml. If I modify the version string of my application in pyproject.toml (or with poetry version) then I need to re-run poetry install for the new version string to be installed in the metadata and take effect, even if I'm still actively developping the project.