88

I can't figure out how to make setup.py add a scrip to the the user's /bin or /usr/bin or whatever.

E.g., I'd like to add a myscript.py to /usr/bin so that the user can call myscript.py from any directory.

Aaron Yodaiken
  • 19,163
  • 32
  • 103
  • 184
  • Try [this example](https://chriswarrick.com/blog/2014/09/15/python-apps-the-right-way-entry_points-and-scripts/). By default, `python setup.py install` will install my_project into `/usr/local/bin`. To delete installation, run `python setup.py install --record files.txt`, which generates files.txt, and then delete those paths by `rm` – anonymous Mar 31 '17 at 13:33
  • See more detailed instruction: [deployment - How can I use setuptools to generate a console_scripts entry point which calls `python -m mypackage`? - Stack Overflow](https://stackoverflow.com/questions/27784271/how-can-i-use-setuptools-to-generate-a-console-scripts-entry-point-which-calls/27785121#27785121) ■ For Windows in particular, see also [How to use setuptools to install a python script for windows command line? - Stack Overflow](https://stackoverflow.com/questions/35566376/how-to-use-setuptools-to-install-a-python-script-for-windows-command-line) – user202729 Dec 06 '21 at 06:32

4 Answers4

77

Consider using console_scripts:

from setuptools import setup
setup(name='some-name',
      ...
      entry_points = {
              'console_scripts': [
                  'command-name = package.module:main_func_name',                  
              ],              
          },
)

Where main_func_name is a main function in your main module. command-name is a name under which it will be saved in /usr/local/bin/ (usually)

DataGreed
  • 13,245
  • 8
  • 45
  • 64
  • 2
    If you are running `pip3 install --editable .` it will install to the command to `/home/{username}/.local/bin`. If you run `sudo pip3 install --editable .` it will install the command to `/usr/local/bin/` – jmcgrath207 Jan 29 '18 at 04:02
  • On a Mac this also installs to the framework dir (`/Library/Frameworks/Python.framework/Versions/3.7/bin` for me), but not under `/usr` (where my `pip` and `python` are) – jalanb Jul 01 '19 at 01:00
45

The Python documentation explains it under the installing scripts section.

Scripts are files containing Python source code, intended to be started from the command line.

setup(...,
      scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
)

As mentioned here, beside scripts, there is an entry_points mechanism, which is more cross-platform.

With entry_points you connect a command line tool name with a function of your choice, whereas scripts could point to any file (e.g. a shell script).

miku
  • 181,842
  • 47
  • 306
  • 310
  • 4
    That seems to put files into the Python `bin` directory (on my Mac `/opt/local/Library/Frameworks/Python.framework/Versions/3.1/bin/`) but I still cannot run them. – Aaron Yodaiken Jan 30 '11 at 00:03
  • 4
    aharon, depending on how you installed 3.1, you may have to alter your `PATH` in order for the scripts within its bin directory to properly function. See [this answer](http://stackoverflow.com/questions/3487664/getting-python-under-control-on-os-x-setting-up-environment-and-libraries/3489922#3489922) to a previous question for instructions on doing so. – Andrew Jan 30 '11 at 00:12
  • This works for scripts that are not Python scripts as well. Unfortunately it also considers anything including just plain data files in the bin directory to be executable if it is listed there as well. – CMCDragonkai Oct 25 '18 at 05:20
20

There are two ways in order to get a working command line tool from setuptools and PyPI infrastructure:

  1. The "scripts" Keyword Argument
    This allows the command-line execution of everything you want, it can be a Python script, a shell script or something completely different.
  2. The "console_scripts" Entry Point
    This allows Python functions (not scripts!) to be directly registered as command-line accessible tools.
Danny Lessio
  • 607
  • 5
  • 13
  • Alas the first method will put scripts that likely have a ".py" extension into the bin directory AND (I think) don't get adjusted for virtualenvs. U-G-L-Y. Best to use console_scripts. – Chris Cogdon Dec 01 '17 at 19:12
  • @Chris Cogdon, the .py extension is not necessary, at least not for *nix systems (I do have a shebang at the top of the file). You're right about virtual envs not behaving nicely - you've got to go to the environment's bin directory to find your executable. But you can run it from there. – Ben Ogorek Nov 23 '19 at 15:25
15

If you're willing to build and install the entire python package, this is how I would go about it:

  • Edit the setup() function in setup.py to contain a parameter named scripts and set its argument as the location of the file(s) you wish to run from anywhere. e.g.

setup(name='myproject',author='',author_email='',scripts=['bin/myscript.py'])

  • Within the directory that contains setup.py, create a bin directory by typing mkdir bin
  • Add myscript.py to this newly-created bin directory (and make sure it's executable!)
  • cd into the directory that contains setup.py again, and install the entire python package by typing python setup.py install
  • Once the package is installed, you should be able to run myscript.py from anywhere on the system!
wh1tney
  • 1,157
  • 1
  • 9
  • 16
  • what if I want to omit the py extension? Btw, the practice of adding source code in bin directory is somewhat questionable – DataGreed Jul 26 '12 at 13:25
  • @DataGreed If you want to omit the .py extension...omit it :) as long as the file is executable, the extension can be omitted and you could simply run `myscript` from the command line. Forgive my naivete, but why is adding source code in the bin directory questionable? – wh1tney Jul 27 '12 at 17:15
  • It a very-very strange decision. Bin should contain builds, not sources. – DataGreed Jul 30 '12 at 08:05