Strange behaviour of Python when importing something from a symlinked script


J

jamadagni

Hello. Today in relation with a library I was working on I was frustrated by this bug for (I think) over an hour: it has to do with a Python script called via a symlink. To illustrate it I have included a minimal test case tarball at the end of this post in base64. (I used uuencode -m.) Just run sh test.sh at root of the extracted tree to see what's happening.

I am quite (unpleasantly) surprised that when one calls a Python script viaa symlink, and that script asks for a module to be imported, Python searches the directory in which the *target* of the link exists, and uses the version of the library present *there* if any, and raises an exception if not.It even follows a chain of symlinks. Any version of the library present inthe same directory as the (user-called) symlink is ignored. This is quite unexpected and I am thinking of filing a bug about this totally counter-intuitive behaviour.

This is all the more frustrating since running print(os.getcwd()) from the same script correctly prints the current directory in which the *symlink* and not its target exists. (The inlined tarball will demonstrate that.)

Now IIUC the symlink is only a user convenience indicating that I create a virtual file in one place pointing to another file elsewhere. Whatever the rest of the contents of the directory containing the other file is immaterial to me. I am executing a script from a given directory. os.getcwd() correctly prints the path of that directory. I also have a library in that same directory for the script to import. I would expect Python to honour the output of os.getcwd() in doing import too.

I read through http://docs.python.org/3/reference/import.html and didn't seem to find any explanation for this behaviour. (Please point out if I have missed it.)

(Note that the same behaviour does not happen with hardlinks, probably since the filesystem itself shows the whole file as existing at the current location.)

Output of the test.sh script:

**** Trying english/run.py ****
CWD: /tmp/symlink-bug/english
Hello Shriramana!
**** Trying english/run-link.py symlinked to ./run.py ****
CWD: /tmp/symlink-bug/english
Traceback (most recent call last):
File "run-link.py", line 3, in <module>
from greet import greet
ImportError: No module named greet
**** Trying english/run-link-link.py symlinked to ./run-link.py symlinked to english/run.py ****
CWD: /tmp/symlink-bug/english
Hello Shriramana!
**** Trying sanskrit/run-slink.py symlinked to english/run.py ****
CWD: /tmp/symlink-bug/sanskrit
Hello Shriramana!
**** Trying sanskrit/run-hlink.py hardlinked to english/run.py ****
CWD: /tmp/symlink-bug/sanskrit
Namaste Shriramana!

Expected output: (see esp items marked 1 and 2 below):

**** Trying english/run.py ****
CWD: /tmp/symlink-bug/english
Hello Shriramana!
1 **** Trying english/run-link.py symlinked to ./run.py ****
CWD: /tmp/symlink-bug/english
Hello Shriramana!
**** Trying english/run-link-link.py symlinked to ./run-link.py symlinked to english/run.py ****
CWD: /tmp/symlink-bug/english
Hello Shriramana!
2 **** Trying sanskrit/run-slink.py symlinked to english/run.py ****
CWD: /tmp/symlink-bug/sanskrit
Namaste Shriramana!
**** Trying sanskrit/run-hlink.py hardlinked to english/run.py ****
CWD: /tmp/symlink-bug/sanskrit
Namaste Shriramana!

Test-case tarball:

begin-base64 664 symlink-bug.tar.gz
H4sIAGoJnlECA+1ay27aQBT1tv6KG1eRQqqYeXqkbNtFV920UtcOTLATPEYz
gyr+vjOAA5F4mMoGpczZWJ6XbY7PmXuvMYtqWqrXh6f5ZBj1BOQgBPdHLDja
PjaIMMFMMMQIde2YYsIi4NEZMDc21wCRyasXled7xx3r/6AwW/ybXJlXXdrh
BflnCDv+mchI4P9i/Ou5ejC+OZ0tOuNfHOefCoE8/8S5AIqApOlQqsm0NIW/
pW5uJvDfjv+iW/6zjO3l39n9xv+5178gDEeAgv57R1nNam2hNvFMl8rCHSRf
f397hAS+uMZ0Iu3oz/huAIP4WdcVTLSUFtaTlifxqsnN+1noUudVrvLEDY8C
Pqz+l5R2Z7fH9I8yvvZ/JrDfJ3DGMhr0fw6M5TM0ClZ5JWEAj/GnNy/44fRs
rIRbc5PA7XpE0Pb/qX+/7Xe36/9D/McQxcv4DyHq9E96D/6C/rf5t9LY1BS9
5P+H/F9wtuF/mf8zxoL/nwWfb2D4VKqhKeLRGNaCi+WoqCG5d4BfelGqCbyX
IviuJJ4tbFErWLUdntQYC6xfODkGW0O6b71meItFD6y8u+vIo7xb1P8oLgtt
IqMdt7MzaT7tgmb/w+5MyaDI9bj98s20uIX/92KzJ+V/K/0TwYP+Q/4XcM79
vzGSPvTftv5LReb1zwUK9d9L8d91HnBC/E84oT7+J5yv6r99hv6B/8P8d/US
nMJ/5oSPiDvJ3vjvJScN/O/nv+PyX4v6H93U//Cy/kc8/yH+u3j977ucTutQ
/buu+K/rPfeo/rf//+G//xFGEY0An+Pj5JXrPyAg4HrxF+ByMi4AKAAA
====
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top