from __future__ import absolute_import ?

Peter Otten __peter__ at web.de
Fri Feb 9 05:27:57 EST 2007


Ron Adam wrote:

> Peter Otten wrote:
>> Ron Adam wrote:
>>
>>>
>>> work
>>>   |
>>>   |- foo.py            # print "foo not in bar"
>>>   |
>>>   `- bar
>>>       |
>>>       |- __init__.py
>>>       |
>>>       |- foo.py        # print "foo in bar"
>>>       |
>>>       |- absolute.py   # from __futer__ import absolute_import
>>>       |                # import foo
>>>       |
>>>       `- relative.py   # import foo
>>>
>>>
>>> * Where "work" is in the path.
>>>
>>>
>>> (1)
>>>
>>> C:\work>python -c "import bar.absolute"
>>> foo not in bar
>>>
>>> C:\work>python -c "import bar.relative"
>>> foo in bar
>>>
>>>
>>> (2)
>>>
>>> C:\work>python -m "bar.absolute"
>>> foo not in bar
>>>
>>> C:\work>python -m "bar.relative"
>>> foo not in bar
>>>
>>>
>>> (3)
>>>
>>> C:\work>python
>>> Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
>>> (Intel)] on win 32
>>> Type "help", "copyright", "credits" or "license" for more information.
>>>  >>> import bar.absolute
>>> foo not in bar
>>>  >>> import bar.relative
>>> foo in bar
>>>
>>>
>>> (4)
>>>
>>> C:\work>cd bar
>> 
>> A path below the package level is generally a good means to shoot
>> yourself in the foot and should be avoided with or without absolute
>> import.
> 
> Seems so.  :-/
> 
> 
>>> C:\work\bar>python -c "import bar.absolute"
>>> foo in bar
>>>
>>> C:\work\bar>python -c "import bar.relative"
>>> foo in bar
>>>
>>>
>>> (5)
>>>
>>> C:\work\bar>python
>>> Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
>>> (Intel)] on win 32
>>> Type "help", "copyright", "credits" or "license" for more information.
>>>  >>> import bar.absolute
>>> foo in bar
>>>  >>> import bar.relative
>>> foo in bar
>>>  >>>
>>>
>>>
>>>
>>> Case (2) seems like it is a bug.
>> 
>> I think so, too.
> 
> This one is the reasons I had trouble figuring it out.  I was using the -m
> command option when I tried to test it.
> 
> There is a bug report on absolute/relative imports already.  I'm not sure
> if
> this particular item is covered under it or not.  Doesn't sound like it as
> the bug report address the relative aspects of it.
> 
> 
>>> Why not also have (4), and (5) do the same as cases (1) and (3)?
>> 
>> The work/bar directory is the current working directory and occurs in the
>> path before the work directory.
> 
> Yes. Unfortunately this is a side effect of using the os's directory
> structure
> to represent a python "package" structure.  If a package was represented
> as a
> combined single file.  Then the working directory would always be the
> package directory.
> 
> 
>  > When bar.absolute imports foo python is
>  > unaware that work/bar/foo.py is part of the bar package.
> 
> Umm.... isn't the "bar" stuck on the front of "bar.absolute" a pretty
> obvious
> hint.  ;-)
> 
> If you run the module directly as a file...
> 
>      python bar/foo.py
> or  python foo.py
> 
> Then I can see that it doesn't know.  But even then, it's possible to find
> out.
>   ie... just check for an __init__.py file.
> 
> Python has a certain minimalist quality where it tries to do a lot with a
> minimum amount of resources, which I generally love.  But in this
> situation that
> might not be the best thing.  It would not be difficult for python to
> detect if
> a module is in a package, and determine the package location.  With the
> move to explicit absolute/relative imports, it would make since if python
> also were a little smarter in this area.

I have not used the new import behaviour seriously, but -- I think I like
it :-)

>>> in cases (4) and (5), that is the result I would expect if I did:
>>>
>>>     import absolute       # with no 'bar.' prefix.
>>>     import relative
>>>
>>>
>>>  From what I understand, in 2.6 relative imports will be depreciated,
>>>  and in 2.7
>>> they will raise an error.  (providing plans don't change)
>>>
>>> Would that mean the absolute imports in (4) and (5) would either find
>>> the 'foo not in bar' or raise an error?
>> 
>> No, in 1, 3 -- and 2 if the current behaviour is indeed a bug. This is
>> only for the relative import which would have to be spelt
>> 
>> from . import foo
> 
> Was that a 'yes' for exampels 4 and 5, since 1,2 and 3 are 'no'?

(4) and (5) are misconfigurations, IMHO.

>> in an absolute-import-as-default environment;
>> 
>> import foo
>> 
>> would always be an absolute import.
> 
> But what is the precise meaning of "absolute import" in this un-dotted
> case?
> 
> Currently it is:
> 
>      "A module or package that is located in sys.path or the current
>      directory".
> 
> But maybe a narrower interpretation may be better?:
> 
>      "A module or package found in sys.path, or the current directory
>       and is *not* in a package."

You'd have to add a not-in-package test to every import - I don't think it's
worth the effort.

> If it's in a package then the dotted "absolute" name should be used.
> Right?

Either that or the full path. The dotted path makes it easy to move the
module between packages.

> I guess what I'm getting at, is it would be nice if the following were
> always true.
> 
>      from __import__ import absolute_import
> 
> 
>      import thispackage.module
>      import thispackage.subpackage
> 
>        # If thispackage is the same name as the current package,
>        # then do not look on sys.path.
> 
> 
>      import otherpackage.module
>      import otherpackage.subpackage
> 
>        # If otherpackage is a different name from the current package,
>        # then do not look in this package.
> 
> 
>      import module
>      import package
> 
>        # Module and package are not in a package, even the current one,
>        # so don't look in any packages, even if the current directory is
>        # in this (or other) package.
> 
> 
> If these were always true, :-)  I think it avoid some situations where
> things don't work, or don't work like one would expect.
> 
> In addition to the above, when executing modules directly from a directory
> inside a package, if python were to detect the package and then follow
> these
> same rules.  It would avoid even more surprises.  While you are editing
> modules in a package, you could then run them directly and get the same
> behavior you get if you cd'd out of the package and then ran it.
> 
> All in all, what I'm suggesting is that the concept of a package (type) be
> much
> stronger than that of a search path or current directory.  And that this
> would add a fair amount of reliability to the language.

I think if you go that way, ultimately you will need some kind of package
registry. I expect that the new import behaviour will get you 99 percent
there with one percent of the hassle. But we will see...

Peter



More information about the Python-list mailing list