14.08.2011 21:48, OKB (not okblacke) yazmış:
=?UTF-8?B?T2t0YXkgxZ5hZmFr?= wrote:

           It appears that Python is reading "import thetest" as
           importing
thetest.py (the same file that is currently being run).  When it
tries to run that file a second time, the relative import fails.


No, there is no such thing happening. Read the error message more
carefully: the error happens when your code reaches the line "from
.theother import foo", and it fails because you are trying to
execute an "explicit" relative import statement (with leading dot
notation) as introduced by PEP 328. What you see is perfectly
expected behaviour as explained in detail in the PEP because the
python interpreter can only make sense of that statement if that
code is *imported* for use by code that resides *outside* the
package. That error message is what you see when you try to *run* a
package member module which uses explicit relative imports. Let me
try to explain a bit further:

        Yes, such a thing was happening.  (I described the fix in an
answer to my own post.)  You should read PEP 366 to understand what I
was talking about, and what the __package__ variable does.


Hmmm, I have overlooked the middle part of your code. Now I get what you mean. Yes that is happening, you are right and I have given the source of that behaviour in my previous post:

- BIG SOURCE OF CONFUSION: Relative imports (both implicit and explicit) is all about 
imports *inside* packages. When you have 2 scripts app.py and string.py sitting in a 
*non-package* folder (they are called top-level modules), that folder is always the first 
entry in sys.path when you run either of those modules directly, so "import 
string" in app.py will always import the string.py in that folder, not the stdlib 
one. (But not when you try with IDLE!) In this case, if you really want the standard 
module, you must manipulate sys.path before your import statement (or change the name of 
your local string.py). THE PEP (328) HAS NO EFFECT IN THAT CASE!

In your case, you are not using the package by importing its members from code outside the package but you are running them directly. So, your files thetest.py and theother.py are now *top-level* modules for the interpreter, not package members. So as per PEP 366, you need to add that boilerplate to set the __package__ attribute.

But the "from __future__ import absolute_import" statement has no effect on the "import thetest" statement when you run the file directly: then thetest.py is a top level module, and when the interpreter encounters the statement "import thetest" *it is already absolute import* (whether you issed the __future__ statement or not). It still is in Python 2.7. PEP 328 has no effect in this case. Remember that absolute import means importing from sys.path only. In this case, thetest.py's folder is always the first entry in sys.path so it tries to import itself first. You would also see the same behaviour if your "import thetest" statement was in theother.py, it would import thetest.py rather than the package. So as I have said before and quoted above, in this case you have to manipulate sys.path, which you have found out yourself.

So what is this "absolute import" thing that is introduced by PEP 328 then? It is all about import statements in package members when they are imported from code outside the package. Before PEP 328, if theother.py contained an "import thetest" statement and if you fired up your interpreter and issued

        import thetest.theother

that "import thetest" in theother.py would find thetest.py. It was considered to be a(n implicit) package-relative import. After PEP 328, if you add to the top of theother.py or issue at the interpreter

        from __future__ import absolute_import

and then issue

        import thetest.theother

the "import thetest" statement in theother.py will find the *package* thetest because sys.path is given priority over the package dir by the __future__ statement. So the PEP has effectively overthrown the convention of treating such imports as special. They are not treated as special anymore and receive the same treatment as other imports. This is one aspect of the PEP. The PEP also defines a new notation (leading dot) for those who want the sibling thetest.py, which is another aspect.

But when you run the theother.py directly, the PEP and the __future__ statement has NO EFFECT. The "import thetest" statement in theother.py is not seen as intra package import by the interpreter so it is already absolute import (uses sys.path) So it finds thetest.py because it is in the same folder as theother.py, which is the first folder in sys.path. Many people are confused and think that this is relative import. It's not. It is already absolute import (from sys.path) and the PEP has nothing to do with it. Now we can answer your critical question:

But why?  That __future__ import is supposed to make absolute
imports the default, so why is "import thetest" importing thetest.py
instead of the package called thetest?

Bacause you are running it directly and the PEP and the __future__ statement does not apply here.

I hope it is clear now.

--
Oktay Şafak
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to