I have a simple python application where my directory structure is as follows:
- project/
- main.py
- config.py
- plugins/
- plugin1
- plugin2
- ...
Config.py only loads configuration files, it does not contain any configuration info in itself.
I now want to distribute this program, and I thought I'd use setuptools to do it. The file users are expected to use is main.py, so that one clearly goes into /usr/bin and the rest of the files go into /usr/share/project.
But there's one problem: I would somehow need to tell main.py to look for config.py in the share directory. But I can't really be sure where exactly the share directory is since that's up to setuptools, right?
What's the best practice when distributing Python-based applications?
1 Answer 1
setuptools install your package in a location which is reachable from python i.e. you can import it:
import project
the problem raise when you do relative imports instead of absolute imports. if your main.py imports config.py it works because they live in the same directory. when you move your main.py to another location like /usr/bin or another location present in PATH environment variable, python try to import config.py from sys.path and not from your package dir. the solution is to use absolute import:
from project import config
now main.py is "movable".
another solution, which i prefer, is using automatic script creation offered by setuptools.
instead of having your code in a
if __name__ == "__main__":
# here all your beautiful code
statement, put your code in a function (main could be a good name):
def main():
# put your code here
if __name__ == "__main__": # not needed, just in case...
main()
now modify your setup.py:
setup(
# ...
entry_points = {
"console_scripts": [
# modify script_name with the name you want use from shell
# $ script_name [params]
"script_name = project.main:main",
],
}
)
that's all. after an install setuptools will create a wrapper script which is callable from shell and that calls your main function. now main.py can live in your project directory and you don't need anymore to move it in a bin/ directory. note that setuptools automatically puts this script in the bin/ directory relative to the installation prefix.
es.
python setup.py install --prefix ~/.local
install your project package in
~/.local/lib/python<version>/site-packages/<package_name>
and your script in
~/.local/bin/<script_name>
so be sure that ~/.local/bin is present in your PATH env.
more info at: http://peak.telecommunity.com/DevCenter/setuptools#automatic-script-creation
6 Comments
/usr/share/config.py? this is not a good way to let the user customize the behavior of your application. a better solution is a per user configuration file like $HOME/.projectrc ad maybe a global configuration in /etc/. if this is your problem i'll correct my answer.from mypackage import config. even if "main.py" and "config.py" are in the same directory i think that this a good practice. (are you using import config in your "main.py"?). with "console_script" entry point you leave the main.py script in your package and automatically setuptools create a wrapper script that call the function you choose.