Problem - Shifting from non-virtual to a conda virtual environment causes console script entry points to be unrecognized.
Background - I recently tried to get religion about using virtual environments for my Python projects. I decided to do this after update to macOS Catalina caused all of my PyCharm projects to show invalid interpreter errors. I thought "What could go wrong throwing one big mess on top of another?" Two days later I could finally run a script again - the worst brick wall I've ever hit. I was not able to find a solution anywhere, so I'm writing my first SO question and my solution to follow, thinking I might finally have something worthy of contributing back to this site I've used so much for so long.
My setup
Context - I develop several interacting data science packages and locally install these in editable mode as a general practice via:
My_Machine:my_package my_user_name$ pip install -e .
I create python packages using a setup.py file with setuptools, building using PyCharm. Within the setup.py file, I define console script entry points like this:
setup.py:
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
setup(...
name='my_project',
entry_points={'console_scripts':['my_entry_name=my_package.scripts.my_python_script:main'
]},
...
)
Before shifting to a conda virtual environment, I was running script perfectly fine for years via a batch file like this:
my_batch_file.command:
#!/bin/bash
cd "$(dirname "$0")" # set the working directory as the command file locations
my_entry_name <script arguments>
However, after shifting to a conda virtual environment, running the command file produces a my_entry_name: command not found
error.
Things tried so far
which python
terminal command. I can see that the default is /Users/my_user_name/anaconda3/bin/python
and if I do this from the command prompt within my project, I see /Users/my_user_name/anaconda3/envs/my_env/bin/python
, reflecting the environment version as expected./Users/my_user_name/anaconda3/envs/my_env/bin/my_entry_name
to see how the shebang line indicates the python version, which was #!/Users/my_user_name/anaconda3/envs/my_env/bin/python
None of this worked - same my_entry_name: command not found
error. Extremely frustrating two days.
Revised answer after further input and experimenting. I've found two options where both require knowing where the actual file is that defines the entry point. For a conda virtual environment, it will be here:
/anaconda3/envs/my_env_name/bin/entry_point_name
There is no need to specify the python version or to activate the environment if this file is called. I've found two ways to do this:
Option 1 - Credit to @sinoroc who first pointed out the virtual environment does not need to be activated if the entry point is called correctly. For a conda virtual environment, that would be:
my_batch_file.command
#!/bin/bash
cd "$(dirname "$0")" # set the working directory as the command file locations
~/anaconda3/envs/my_env_name/bin/entry_point_name <my script args>
For other types of virtual environments, you would just adjust the path details to get to the entry point file.
Option 2 - If you place a copy of the entry point file in the main Anaconda bin:
/anaconda3/bin/my_entry_name
you don't need to specify the path, letting you call the entry point like they should work, imho - ie shields the script user from language and install details:
my_batch_file.command
#!/bin/bash
cd "$(dirname "$0")" # set the working directory as the command file locations
entry_point_name <my script args>
As this manual copy step is not elegant, I have posted a question about how to do this better: How do you make an entry point to a script in a virtual environment available system-wide?