11

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.

2
  • What sorts of things will these "scripts" do? Commented 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? Commented Jan 29, 2016 at 12:13

3 Answers 3

7

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:

https://github.com/jacebrowning/gdm/blob/fa998167f5f6de64bc8bdfd8b9433870d79ef814/gdm/cli.py#L161-L162

3
  • I know, I said in my question that it's possible. The question is which method is preferable.
    – wrgrs
    Commented 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. Commented Jan 28, 2016 at 22:52
  • I gave a more concrete example.
    – wrgrs
    Commented Jan 29, 2016 at 8:13
6

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
1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.