In my Python application, I can distinguish between entry points (scripts) and what I think of as library code.
My instinct is to put the library code inside a package, and the scripts elsewhere importing from the package.
It is possible using setup.py to reference methods inside a package to use as entry-points, thereby having all Python code inside packages.
Which is preferable?
Note: this link discusses both options but doesn't really offer an opinion.
Edit: to give a more concrete example, I am reviewing some code which contains one package. There are forty modules inside it:
__init__.py
- 11 'scripts'
- 10 'library modules' used by those scripts
- 18 test modules
This doesn't feel like it is using the capability of packages very well, but I can't put my finger on what exactly is wrong.
I appreciate that having tests in the same package was not in my original question.
-
What sorts of things will these "scripts" do?Jace Browning– Jace Browning2016年01月28日 22:48:14 +00:00Commented Jan 28, 2016 at 22:48
-
Do you expect the scripts and the library to rev separately or do they need to be developed together?Jace Browning– Jace Browning2016年01月29日 12:13:50 +00:00Commented Jan 29, 2016 at 12:13
3 Answers 3
Yes, this is possible and quite common for packages that serve as both command-line tools and imported libraries.
In setup.py
, add a module's function as an entry point:
setuptools.setup(
...
entry_points={'console_scripts': [
'foo = my_package.some_module:main_func',
]},
...
)
To create a script named foo
that calls the my_func
function inside of my_package.some_module
. Read more at https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation.
It is also a convention it to add:
#!/usr/bin/env python
...
if __name__ == '__main__':
my_func()
to the modules that can be called as "scripts" where my_func
is the function you'd like to call externally.
Here is an example of setup.py
:
https://github.com/jacebrowning/gdm/blob/fa998167f5f6de64bc8bdfd8b9433870d79ef814/setup.py#L28-L31
and a callable module:
-
I know, I said in my question that it's possible. The question is which method is preferable.wrgrs– wrgrs2016年01月28日 22:35:45 +00:00Commented Jan 28, 2016 at 22:35
-
Preferable to whom? This method let's you share code in the case where you'd like to additionally make the entry points callable from Python.Jace Browning– Jace Browning2016年01月28日 22:52:27 +00:00Commented Jan 28, 2016 at 22:52
-
I gave a more concrete example.wrgrs– wrgrs2016年01月29日 08:13:06 +00:00Commented Jan 29, 2016 at 8:13
Two years later, I feel that I can answer my own question.
It is preferable to use the Setuptools entry_points
method. This is described well in the Click documentation, and the main points are:
- this works better on Windows
- the Pythonpath is managed by Setuptools, so (for example) if your script is installed inside a virtualenv, you don't need to activate the virtualenv for it to work correctly
If you intend to have the library code be used by other packages, you need to separate it from the scripts. This is due to the way dependencies are declared in setup.py and requirements.txt (see here).
If the library code will only be used with these scripts, you can choose. I would choose to keep them together to keep things a little simpler