I'm trying to have a Python script available on a user's path when they install my package from PyPI using pip
:
pip install MyPackage
MyPackage
is on PyPI and installs successfully--apparently--in a conda
virtual environment. The setup.py
file (excerpted) looks like this:
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
config = {
'name': 'MyPackage',
'version': '0.2.1.dev',
'install_requires': [...],
'packages': [
'MyPackage', 'MyPackage.utils'
],
'py_modules': [
'MyCLI',
],
'scripts': [
'MyPackage/MyCLI.py',
],
...
On GNU/Linux, when I type MyCLI
and hit Tab, it successfully auto-completes to MyCLI.py
. When I ask which MyCLI.py
it shows me the fully qualified path to Python script in the virtual environment folder:
$ which MyCLI.py
/home/arthur/Applications/miniconda3/envs/MyPackage/bin/MyCLI.py
MyCLI.py
uses fire
to wrap a Python class, expose its methods at the command line, present docstrings as help documentation, and parse arguments. It looks like:
'''
My Command Line Interface
'''
class CLIRuntime(object):
def run(self):
do_something()
if __name__ == '__main__':
import fire
fire.Fire(CLIRuntime)
If I run this script with the Python interpreter, it executes correctly.
python $(which MyCLI.py)
The problem is, when I try to run it without specifying the Python interpreter, it seems to think it is a bash script or binary file and wrecks my terminal session:
$ MyCLI.py
/home/arthur/Applications/miniconda3/envs/MyPackage/bin/MyCLI.py: line 8:
My Command Line Interface
: No such file or directory
from: can't read /var/mail/__future__
How can I change setup.py
so that this script is available on a user's path but also known as/ runs as a Python script?
I want to note that if I install this package from source using pip
in editable mode (pip install -e .
), MyCLI.py
is on my path and runs correctly as a Python script. It just doesn't appear to work when installing from PyPI.
To tell your shell what program should be used to execute a script file, you need to add a "hash-bang" declaration as the first line in the script. For Python executing inside of a virtualenv, either
#!python
or
#!/usr/bin/env python
will do the trick. If you're using Python 3, use python3
instead.