I want to use Fish shell to iterate through Python virtual environments and print a two-column table showing (1) the virtual environment name and (2) that environment’s Python version in parentheses:
ansible (3.7.7)
cookiecutter (3.7.8)
pelican (3.7.8)
tempenv-0f20326801926 (broken)
tempenv-1b0a326016370 (3.8.5)
wagtail (broken)
Running python --version
for a given environment normally yields its version number. If the symlinked Python interpreter no longer exists, however, an error like the following will be returned:
dyld: Library not loaded: @executable_path/../.Python
Referenced from: /Virtualenvs/tempenv-0f20326801926/bin/python
Reason: image not found
fish: '/Virtualenvs/tempenv-0…' terminated by signal SIGABRT (Abort)
In the latter case, the virtual environment is broken, so I want to set the Python version number to broken
while suppressing all error output, so that the user only sees the printed table and not the errors.
I’ve been able to suppress the first three lines of the above error output — but not the fourth — via the following stanza:
begin; pushd $VIRTUALENV_HOME; and set -e dirprev[-1]; end
for i in */bin/python
set -l python_version
if test -x "$VIRTUALENV_HOME/$i"
set -l test_python ("$VIRTUALENV_HOME/$i" -V >/dev/null 2>/dev/null)
if test $status -eq 0
set python_version ("$VIRTUALENV_HOME/$i" -V | string split " ")[2]
else
set python_version broken
end
else
set python_version broken
end
printf "%-33s (%s)\n" $i $python_version
end | sed "s|/bin/python||"
begin; popd; and set -e dirprev[-1]; end
But try as I might, I cannot figure out how to suppress the fish: '[…]' terminated by signal SIGABRT (Abort)
lines:
ansible (3.7.7)
cookiecutter (3.7.8)
pelican (3.7.8)
fish: Job 4, '"$VIRTUALFISH_HOME/$i" -V >/dev…' terminated by signal SIGABRT (Abort)
tempenv-0f20326801926 (broken)
tempenv-1b0a326016370 (3.8.5)
fish: Job 4, '"$VIRTUALFISH_HOME/$i" -V >/dev…' terminated by signal SIGABRT (Abort)
wagtail (broken)
How can I improve the above stanza and eliminate the unhelpful error messages from the printed table?
The thing to note is the error you can't suppress is coming from the shell that is executing your script. It is not being written by the failing python command. The solution is to use another shell level so you can suppress that job control error message from that shell while still capturing the stdout of the command you're interested in:
set -l test_python (fish -c "'$VIRTUALENV_HOME/$i' -V" 2>/dev/null)