A change of env
January 2, 2018 at 10:18 PM by Dr. Drang
Two years after resolving to switch to Python 3, I’ve done it. I believe it will stick because I’ve changed my defaults.
Pretty much since I first started using Anaconda, I’ve had a Python 3 environment installed alongside Python 2, but Python 2 was the default. Still is, but now I’ve fiddled a bit with my .bashrc
to change the environment whenever I launch a new Terminal window. Here are the important lines:
# Anaconda Python
export PATH=$HOME/anaconda/bin:$PATH
source activate py3
The export
line has always been there, and it’s still necessary to make all the Anaconda commands available. The source
line is the new addition. It activates the Python 3 environment, which I called py3
back when I first installed it. So here’s how things work now from the shell:
jupyter console
starts a Jupyter session running Python 3.- Scripts with a shebang line of
#!/usr/bin/env python
use the Python 3 at~/anaconda/envs/py3/bin/python
. - Scripts with a shebang line of
#!/usr/bin/env python2
use the Python 2 at~/anaconda/bin/python2
. - Scripts with a shebang line of
#!/usr/bin/env python3
use the Python 3 at~/anaconda/envs/py3/bin/python3
. Because of soft links in the Anaconda setup, this is the same Python 3 that#!/usr/bin/env python
uses.
When I first did this, I found that Anaconda had changed my bash prompt, adding a (py3)
to the front of it to let me know which environment I’m working in. I hated that, so I ran
conda config --set changeps1 False
to get rid of it. This added a line to my ~/.condarc
,
changeps1: False
so the fix is persistent and I don’t need to add the conda config
line to my .bashrc
.
With this change, all my scripts with shebang lines of #!/usr/bin/env python
are likely to fail because they were written with the expectation of Python 2 as the active environment. No problem. I ran the following pipeline from within my ~/Dropbox/bin
directory, where I keep all my scripts. Now all those scripts have a shebang line of #!/usr/bin/env python2
.
grep -l '^#!/usr/bin/env python$' * 2>/dev/null | xargs -n 1 perl -i -pe 's/python/python2/ if $.==1'
The grep -l
part gets a list of all the files with a #!/usr/bin/env python
shebang line. The 2>/dev/null
isn’t necessary, but it silences the error messages grep
spits out when it encounters a directory instead of a regular file.
The list of files from grep
is then fed to xargs
, which sends them one at a time (that’s the -n 1
switch) to perl
, which edits the file in place (-i
), substituting python2
for python
on the first line.
The -n 1
option to xargs
is important because without it, xargs
would feed the entire list of files to perl
at once, and Perl’s $.
variable would be interpreted as the first line of a concatenation of all the files. Only the first file in the list would get the change. With the -n 1
option, the perl
command is called many times, each time with only one file argument, and all the files get changed.1
I also have a bunch of scripts with a shebang line of #!/usr/bin/python
, which use the Apple-supplied Python 2. These scripts won’t fail because they call the same version Python they were written for, so I don’t feel any need to change them.
-
If you’re wondering whether I knew to include the
-n 1
switch when I ran the command the first time, wonder no more. Of course I didn’t. ↩