Python – How to get ‘realpath’ to find the symbolic link

pythonsymlink

I am on MacOSX using bash as my shell. I have symbolic link, created like this:

ln -s /usr/bin/python python2 

I have a package that uses python2 and I want to create a symbol link in my current working directory to /usr/bin/python which is actually python2. When I do a python2 from the command line I get this error:

python2: realpath couldn't resolve "/usr/bin/python2"

But invoking it like this ./python2 resolves the path correctly. My PATH has . in it. In fact I modified it, for testing, to only have . in it.

How do I resolve this? Thanks!


Context

A number of the suggested solutions below won't work for me. I tried to distill my question as focused and brief as possible so that people wouldn't drown in a sea of text, but clearly I need to provide more background.

I'm trying to do develop on a package that I cloned from git. The original package, git-multimail, is/was developed on some variant of Linux (I'm guessing Ubuntu). I've been trying to modify it to be able to use it and its test suite on MacOSX with as little modification as possible. Here's why some of the proposed solutions aren't ideal:

  1. As root, create a python2 symlink in /usr/bin/. I'm looking for a solution that wouldn't require this. This was an obvious option at the beginning, but I'd like a solution that modifies the host system as little as possible. This is why I wanted to create a temporary symlink in the current working directory, add the CWD (i.e. .) to my path, and then destroy this when finished (i.e. the symlink).

  2. Create a wrapper script to call the python script with the existing python. The problem with this is that much of the test suite uses the actual script_files as executables, depending on shebang to find the correct execution environment. This would mean editing the test suite considerably. In this context, (see below for a snippet of the test-framework), I would have to add a wrapper for every .py file; further the user/developer would have to be aware of different rules for using the package depending on what system they are on (i.e. on MacOSX make sure you don't use the python files without invoking them via the wrapper or explicitly calling /usr/bin/python file.py).

    #! /bin/sh
    
    D=$(cd $(dirname "$0") && pwd)
    MULTIMAIL="$D/../git-multimail/git_multimail.py"
    POST_RECEIVE="$D/../git-multimail/post-receive"
    
    TESTREPO=$("$D/create-test-repo")
    
    HOME="$D"
    XDG_CONFIG_HOME="$D"
    GIT_CONFIG_NOSYSTEM=1
    export HOME XDG_CONFIG_HOME GIT_CONFIG_NOSYSTEM
    
    cd $TESTREPO
    
    test_email() {
        REFNAME="$1"
        OLDREV="$2"
        NEWREV="$3"
        echo "$OLDREV" "$NEWREV" "$REFNAME" | USER=pushuser "$MULTIMAIL"
    
    } 
    
  3. Changing all python2 references to python. The README suggests this, but this effectively makes version control useless since the system sees the change as new version, when in fact it's not (semantically).

I've been using (3) but I'm trying to find a better solution. I'm willing to accept that this is just the way things are (i.e. there's not a suitable way to point 'python2' to /usr/bin/python that is portable and unobtrusive without a lot of changes to the test suite and actual framework).

Best Answer

If you need to resolve (or investigate) a symlink you can use the platform independent bash library 'realpath-lib'. By default it emulates readlink and will work on Mac or Unix. It can be found on Github or Bitbucket and it's free.

But it sounds like you want to just do python2 (rather than ./python2) from your local (working) directory. It might be possible to do this with an alias in your .bashrc or otherwise you will need to add the working directory (that contains your symlink) to your PATH environment variable. This can also be done for the current session only or within the .bashrc file for future sessions. This could be a solution for just a specific user.

Another option that would work for all users would be to create the python2 symlink to /usr/bin/python in another directory on the path, say in /usr/local/bin. Perhaps something like:

sudo ln -s /usr/bin/python /usr/local/bin/python2

Then any user or script should find the python or python2 commands. Of course this option requires admin (root) privileges to install.

Related Question