[Python-ideas] [Python-Dev] If you shadow a module in the standard library that IDLE depends on, bad things happen

Chris Angelico rosuav at gmail.com
Sun Nov 1 02:36:08 EST 2015


On Sun, Nov 1, 2015 at 5:06 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> (1) Beginning with Python 3.6, the default is that the current directory
> is put at the end of sys.path rather than the beginning. Instead of:
>
>     >>> print(sys.path)
>     ['', '/this', '/that', '/another']
>
> we will have this instead:
>
>     >>> print(sys.path)
>     ['/this', '/that', '/another', '']
>
> Those who don't shadow installed packages won't notice any
> difference.
>
> Scripts which deliberately or unintentionally shadow installed packages
> will break from this change. I don't have a problem with this. You can't
> fix harmful behaviour without breaking code that depends on that harmful
> behaviour. Additionally, I expect that those who rely on the current
> behaviour will be in a small minority, much fewer than those who will be
> bitten by accidental shadowing into the indefinite future.

+1. As Serhiy says, though, this will additionally break scripts that
_protect against_ shadowing. We could have an easily-recognized shim
in slot zero, as a compatibility measure; not duplicating the next
one, but a clearly invalid entry. I suggest None, which appears to
work:

rosuav at sikorsky:~$ python3
Python 3.6.0a0 (default:9ca59b3cc18b, Oct 16 2015, 15:25:11)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path[0]=None; sys.path.append("")
>>> open("string.py","w").write("print('I am a string!')")
23
>>> import string
>>> string
<module 'string' from '/usr/local/lib/python3.6/string.py'>
>>> import doesntexist
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'doesntexist'
>>> open("uniquename.py","w").write("print('I have a unique name.')")
30
>>> import uniquename
I have a unique name.

The None entry is happily ignored. Shim removal with "if not
sys.path[0]: sys.path.pop(0)" will still remove it.

But I had a quick look at the link Serhiy posted, and two of the three
entries that I dug into were actually not removing the blank entry
(the other removed it and replaced it with a hard path); they had
previously inserted something at the beginning of sys.path, and were
removing _that_ entry. They won't need to be changed. I did a similar
search on GitHub and, again, most of the results weren't actually
removing the '' entry from the beginning. So the None could be put
there as a compatibility measure for 3.6, and then dropped in 3.7 - or
even just left out altogether, so a small number of programs break.

Would have been nice to do this at Python 3.0, as it'd have been on
par with absolute imports and other edge cases. Oh well.

ChrisA


More information about the Python-ideas mailing list