How can I get the version defined in setup.py (setuptools) in my package?
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.
example study: mymodule
Imagine this configuration:
setup.py
mymodule/
/ __init__.py
/ version.py
/ myclasses.py
Then imagine some usual scenario where you have dependencies and setup.py
looks like:
setup(...
install_requires=['dep1','dep2', ...]
...)
And an example __init__.py
:
from mymodule.myclasses import *
from mymodule.version import __version__
And for example myclasses.py
:
# these are not installed on your system.
# importing mymodule.myclasses would give ImportError
import dep1
import dep2
problem #1: importing mymodule
during setup
If your setup.py
imports mymodule
then during setup you would most likely get an ImportError
. This is a very common error when your package has dependencies. If your package does not have other dependencies than the builtins, you may be safe; however this isn't a good practice. The reason for that is that it is not future-proof; say tomorrow your code needs to consume some other dependency.
problem #2: where's my __version__
?
If you hardcode __version__
in setup.py
then it may not match the version that you would ship in your module. To be consistent, you would put it in one place and read it from the same place when you need it. Using import
you may get the problem #1.
solution: à la setuptools
You would use a combination of open
, exec
and provide a dict for exec
to add variables:
# setup.py
from setuptools import setup, find_packages
from distutils.util import convert_path
main_ns = {}
ver_path = convert_path('mymodule/version.py')
with open(ver_path) as ver_file:
exec(ver_file.read(), main_ns)
setup(...,
version=main_ns['__version__'],
...)
And in mymodule/version.py
expose the version:
__version__ = 'some.semantic.version'
This way, the version is shipped with the module, and you do not have issues during setup trying to import a module that has missing dependencies (yet to be installed).
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.
Your question is a little vague, but I think what you are asking is how to specify it.
You need to define __version__
like so:
__version__ = '1.4.4'
And then you can confirm that setup.py knows about the version you just specified:
% ./setup.py --version
1.4.4
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.