Placing current working directory at the beginning of sys.path or the end
of sys.path is a tradeoff between two debugging tasks given the error
message, `AttributeError: 'module' object has no attribute 'blah'`. The
traceback tells you the name of the module. Which would you prefer: (1)
needing to notice that you made a module of the same name, or (2) needing
to notice that somewhere in the cryptic locations on sys.path there's a
module of the same name?
I'll pick option 1. Sure, it's tricky the first time it happens, but I've
seen complete beginners figure it out after a few minutes.
> [Sven R. Kunze]
> > ...
> > Not quite sure if I understand the implementation. Reading this
> > http://mathworld.wolfram.com/BellNumber.html for the given example of 6, it
> > should have 203 possible partitions. What am I missing?
> > [Tim Peters]
> The ActiveState recipe has nothing to do with set partitions. Instead
> it returns all ways of breaking a sequence into a sequence of
> subsequences whose sum (catenation) is the original sequence. If
> there are N elements in the original sequence, there are 2**(N-1) ways
> to do that. That's why there are 32 results in the recipe's example
> output (2**(len("abcdef")-1) == 32). There would be 203 "set
> partitions" of a 6-element set.
@Tim: you are completely right. Sorry for the confusion referencing this implementation. Forget it.
> On Sun, Nov 1, 2015 at 6:37 PM, Brendan Barnwell <brenbarn(a)brenbarn.net> wrote:
> > On 2015-11-01 17:58, David Mertz wrote:
> >> Oh, yeah... I see what you are asking for isn't quite the same thing as
> >> power set. But still, it's not something you can do in finite time with
> >> infinite iterators (nor in tractable time with *large* iterators). So
> >> `itertools` isn't where it belongs.
> > I don't think that reasoning is sound. Itertools already includes
> > several combinatoric generators like permutations and combinations, which
> > aren't computable for infinite iterators and which take intractable time
> > for large finite iterators.
CC'ing Python-Ideas. Follow-ups to Python-Ideas please.
On Thu, Oct 29, 2015 at 09:22:15PM -0400, Terry Reedy wrote:
> Leaving IDLE aside, the reason '' is added to sys.path is so that people
> can import their own modules. This is very useful. Shadowing is the
> result of putting it at the front. I have long thought this a dubious
> choice. If '' were instead appended, people could still import modules
> that did not duplicate stdlib names. Anyone who wanted shadowing could
> move '' to the front. But then shadowing would be intentional, not an
Terry is right. Shadowing should be possible, and it should require a
deliberate decision on the part of the programmer.
Consider the shell, say, bash or similar. My understanding is that the
shell PATH deliberately excludes the current directory because of the
possibility of malicious software shadowing usual commands in /bin etc.
If you want to run an executable in the current directory, you have to
explicitly provide the path to it: ./myscript rather than just myscript.
Now Python isn't exactly the shell, and so I'm not proposing that Python
does the same thing. But surely we can agree on the following?
- Shadowing explicitly installed packages, including the stdlib, is
- But when shadowing occurs, it is *nearly always* accidental.
- Such accidental shadowing often causes problems.
- And further more, debugging shadowing problems is sometimes tricky
even for experienced coders, and almost impossible for beginners.
(It's not until you've been burned once or thrice by shadowing that
you recognise the symptoms, at which point it is then usually easy to
- Hence, we should put the onus on those who want to shadow installed
packages) to do so *explicitly*, or at least make it easier to avoid
I propose the following two changes:
(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:
['', '/this', '/that', '/another']
we will have this instead:
['/this', '/that', '/another', '']
Those who don't shadow installed packages won't notice any
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. And if you
want the old behaviour back, it is easy to do so, by changing the path
before doing your imports:
if sys.path[-1] == "": sys.path = [""] + sys.path[:-1]
I do not belive that it is onerous for those who want shadowing to have
to take steps to do so explicitly. That can be added to your scripts on
a case-by-case basis, or your PYTHONSTARTUP file, by modifying your
site.py, or (I think) by putting the code into the sitecustomize or
(2) IDLE doesn't need to wait for Python 3.6 to make this change. I
believe that IDLE is permitted to make backwards incompatible changes in
minor releases, so there is no reason why it can't change the path
That's a simpler fix than scanning the entire path, raising warnings
(which beginners won't understand and will either ignore or panic over)
or other complex solutions. It may not prevent *every* shadowing
incident, but it will improve the situation immeasurably.
This idea results from issue of user files shadowing stdlib files on
import. There was a thread on pydev about this yesterday. There is
also an opposite issue of builtin modules shadowing user files.
The keyword module provides kwlist and iskeyword function. One use of
kwlist is used in some other stdlib modules and can be used by syntax
highlighters (as in IDLE). Kwlist is updated by the main function.
A module module would have at least liblist and islibmodule function.
Liblist would contain all directories with __init__.py and all .py
files. (I don't think files within package directories should be
included, as there is no direct shadowing problem.) A python oriented
editor could then warn on save requests "This name matches a stdlib name
in /Lib. If you run python in this directory, you will not be able to
import the stdlib module. Continue?".
The module should also have binlist and isbinmodule for builtin modules.
(I do not know how to get such a list. If necessary, an api could be
added.) An editor could than warn "This name matches a builtin stdlib
name. You will not be able to import this file. Continue?".
Terry Jan Reedy