On Thu, Dec 10, 2020 at 1:22 PM Steven D'Aprano <st...@pearwood.info> wrote:

> On Thu, Dec 10, 2020 at 10:57:32AM -0800, Guido van Rossum wrote:
>
> > All I have to add is that I am appalled that people actually write `from
> > foo import __init__`
>
> I too would be appalled if that was what people are doing, but it isn't.
>
> Looking at the code samples in the wild:
>
> https://github.com/search?l=Python&q=%22from+.__init__+import%22&type=Code
>
> I see no examples of either of the (anti-)patterns given by Gregory in
> his opening post:
>
>     # No examples of either of these.
>     from package import __init__
>     import package.__init__
>
> I have read through the first ten, and last five, pages of the search
> results and what people are doing is typically:
>
>     from __init__ import name
>
> or sometimes with a wildcard import. There are also a few cases using a
> dot:
>
>     from .__init__ import name
>
> and a few cases of attempted bilingual 2 and 3 code:
>
>     try:
>         from .__init__ import name #Python 3
>     except:
>         from __init__ import name
>
>
> So what seems to be happening is that people have a package sub-module,
> say "package/run.py", and in Python 2 code they wanted to import from
> the main package from within run.py.
>

Interesting, since Python 2 also supports relative imports. That last
example makes the intention clear(er) -- as you write they want it to work
both when "run" is imported as a toplevel module and when it is located
inside a package, i.e. "package.run". If all the other code is in
__init__.py that trick will indeed work, but it points to a general lack of
understanding of how packages and import path resolution works. :-(

This would be unrelated to Python 3 (unless their app somehow also evolved
so that their Python 2 version uses a flat namespace while their Python 3
version uses packages).


> I don't know if that is less appalling than what Gregory has told us,
> but it is different, and to my mind at least it makes it more
> understandable and not as weird looking.
>

Well, if I really meant to do something like that I'd write

try:
    from . import name
except ImportError:
    from __init__ import name

but I would never write

from .__init__ import name


> This is nothing like Gregory's characterisation of cargo cult (his term)
> programmers writing `import package.__init__` to import package.
>

Well, depending on where you are in the stack, there may be no way to
distinguish that from other forms involving a dot.



> [...]
> > As for how people can check whether a package is a namespace package,
> there
> > are many other ways to check for that without attempting to import
> > `__init__` from it.
>
> Are these many other ways a secret? *wink* Because if somebody with the
> experience and knowledge of MAL doesn't know them, let alone people like
> me, maybe you should give us a hint what they are.
>

In the below example, foo is a namespace package and bar a classic package.
Behold the differences:
```
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64
bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo, bar
>>> foo
<module 'foo' (namespace)>
>>> bar
<module 'bar' from 'C:\\Users\\gvanrossum\\cpython\\bar\\__init__.py'>
>>> dir(foo)
['__doc__', '__file__', '__loader__', '__name__', '__package__',
'__path__', '__spec__']
>>> dir(bar)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__path__', '__spec__']
>>> foo.__file__
>>> bar.__file__
'C:\\Users\\gvanrossum\\cpython\\bar\\__init__.py'
>>> foo.__path__
_NamespacePath(['C:\\Users\\gvanrossum\\cpython\\foo'])
>>> bar.__path__
['C:\\Users\\gvanrossum\\cpython\\bar']
>>>
```
(Note that `foo.__file__` prints nothing because the value is None.)

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DA2E6PBGDFQ567UPFVPOJNKCRBTPWSFF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to