The Python Oracle

How can I get the version defined in setup.py (setuptools) in my package?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Peaceful Mind

--

Chapters
00:00 How Can I Get The Version Defined In Setup.Py (Setuptools) In My Package?
00:18 Accepted Answer Score 312
01:29 Answer 2 Score 47
03:41 Answer 3 Score 26
04:42 Answer 4 Score 20
05:16 Answer 5 Score 11
06:14 Thank you

--

Full question
https://stackoverflow.com/questions/2058...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #setuptools

#avk47



ACCEPTED ANSWER

Score 313


Interrogate version string of already-installed distribution

To retrieve the version from inside your package at runtime (what your question appears to actually be asking), you can use:

import pkg_resources  # part of setuptools
version = pkg_resources.require("MyProject")[0].version

Store version string for use during install

If you want to go the other way 'round (which appears to be what other answer authors here appear to have thought you were asking), put the version string in a separate file and read that file's contents in setup.py.

You could make a version.py in your package with a __version__ line, then read it from setup.py using execfile('mypackage/version.py'), so that it sets __version__ in the setup.py namespace.

Warning about race condition during install

By the way, DO NOT import your package from your setup.py as suggested in another answer here: it will seem to work for you (because you already have your package's dependencies installed), but it will wreak havoc upon new users of your package, as they will not be able to install your package without manually installing the dependencies first.




ANSWER 2

Score 27


The best technique is to define __version__ in your product code, then import it into setup.py from there. This gives you a value you can read in your running module, and have only one place to define it.

The values in setup.py are not installed, and setup.py doesn't stick around after installation.

What I did (for example) in coverage.py:

# coverage/__init__.py
__version__ = "3.2"


# setup.py
from coverage import __version__

setup(
    name = 'coverage',
    version = __version__,
    ...
    )

UPDATE (2017): coverage.py no longer imports itself to get the version. Importing your own code can make it uninstallable, because you product code will try to import dependencies, which aren't installed yet, because setup.py is what installs them.




ANSWER 3

Score 21


Your question is a little vague, but I think what you are asking is how to specify it.

You can define __version__ like so:

__version__ = '1.4.4'

...or just put it into the setup.py like this:


import setuptools

setuptools.setup(
    name='foobar',
    version='1.4.4',
)

...and they you can confirm that setup.py knows about the version you just specified:

% ./setup.py --version
1.4.4



ANSWER 4

Score 11


I wasn't happy with these answers... didn't want to require setuptools, nor make a whole separate module for a single variable, so I came up with these.

For when you are sure the main module is in pep8 style and will stay that way:

version = '0.30.unknown'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            _, _, version = line.replace("'", '').split()
            break

If you'd like to be extra careful and use a real parser:

import ast
version = '0.30.unknown2'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            version = ast.parse(line).body[0].value.s
            break

setup.py is somewhat of a throwaway module so not an issue if it is a bit ugly.


Update: funny enough I've moved away from this in recent years and started using a separate file in the package called meta.py. I put lots of meta data in there that I might want to change frequently. So, not just for one value.