The problem:
- I don’t understand the difference between
setup.py developandsetup.py install - I don’t understand the difference between
setup.py developandpip install -e [dir] - I don’t see the changes to my code when I import my code
The difference between setup.py develop and setup.py install
In short, you want to run setup.py develop when you are editing code because when you run
setup.py install, it will copy your code into site-packages thus if you want to test your
latest code you will need to install (copy) again. On the other hand, with develop, it creates
a link to your source code so that when you import your code, it is your latest code.
Let’s take a look.
note: to keep it simple, I’m going to assume that you have created virtual environment and using python3.
cd ${project-dir}
python3 -m venv env
source env/bin/activate
pip install -U setuptools
easy_install --version
setuptools 38.5.1 from ${project-dir}/env/lib/python3.6/site-packages (Python 3.6)
setup.py develop simply creates a special .egg-link file in site-packages directory which
links to your project’s source code.
$ cd ${project-dir}
$ python setup.py develop
$ ls -l env/lib/python3.6/site-packages | grep myproject
-rw-r--r-- 1 nreeves staff 44 Mar 5 14:11 myproject.egg-link
$ cat env/lib/python3.6/site-packages/myproject.egg-link
${project-dir}/src
../
When you list package, you can see it shows source directory instead of package name
$ pip list --format=columns | grep myproject
myproject 0.1 ${project-dir}/src
and when you see path to source code, it is the file under my project folder and not inside site-package
>>> import myproject
>>> myproject.__file__
'${project-dir}/src/myproject/__init__.py'
Let’s uninstall that for now so that we can see what install will do.
You can see it is simply removing .egg-link file
$ python setup.py develop --uninstall
running develop
Removing ${project-dir}/env/lib/python3.6/site-packages/myproject.egg-link (link to src)
Spoiler alert!
if you run find . -name 'myproject.*', you will see residual but this is good enough for now.
Now to install with install.
You will see build process then copying bunch of files to site-packages
$ python setup.py install
running install
running build
running build_py
...
copying build... -> ${project-dir}/env/lib/python3.6/site-packages/myproject/...
...
When you list package, you only see package name unlike the one with develop
pip list --format=columns | grep myproject
myproject 0.1
and when you see path to source code, the path to the file is inside of site-packages
>>> import myproject
>>> myproject.__file__
'${project-dir}/env/lib/python3.6/site-packages/myproject/__init__.py'
So the reason you might not see your new code could be:
- At one point you ran
python setup.py installso make sure to remove them. - You made changes and forgot to restart the program. Python will load files when program started, compile it to bytecode and keep it internally.
But wait… instead of setup.py, use pip
It is highly recommended to use pip instead of setup.py.
pip install . instead of setup.py install and
pip install -e . instead of setup.py develop.
Because setup.py will do the wrong things for dependencies such as:
- Setuptools uses easy_install to fulfill these dependencies and it skip pip’s hash-checking
easy_installdoes not exclude pre and post release versions as pip does.easy_installmake the package hard to uninstall things or may not do clean job. Remember the spoiler alert? if you install withpip install -e .and runpip uninstall mypackagethenfind . -name 'myproject.*'won’t find anything.
Cheers!