Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #106447 > unrolled thread

module alias in import statement

Started by"ast" <nomail@com.invalid>
First post2016-04-04 17:31 +0200
Last post2016-04-05 17:47 +1000
Articles 9 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  module alias in import statement "ast" <nomail@com.invalid> - 2016-04-04 17:31 +0200
    Re: module alias in import statement Ned Batchelder <ned@nedbatchelder.com> - 2016-04-04 08:59 -0700
    Re: module alias in import statement Steven D'Aprano <steve@pearwood.info> - 2016-04-05 02:15 +1000
    Re: module alias in import statement Terry Reedy <tjreedy@udel.edu> - 2016-04-04 16:46 -0400
      Re: module alias in import statement Rustom Mody <rustompmody@gmail.com> - 2016-04-04 21:08 -0700
        Re: module alias in import statement Chris Angelico <rosuav@gmail.com> - 2016-04-05 14:23 +1000
          Re: module alias in import statement Rustom Mody <rustompmody@gmail.com> - 2016-04-04 21:27 -0700
            Re: module alias in import statement Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-04-05 17:26 +1000
              Re: module alias in import statement Chris Angelico <rosuav@gmail.com> - 2016-04-05 17:47 +1000

#106447 — module alias in import statement

From"ast" <nomail@com.invalid>
Date2016-04-04 17:31 +0200
Subjectmodule alias in import statement
Message-ID<570288d0$0$19758$426a74cc@news.free.fr>
hello

>>> import tkinter as tk
>>> import tk.ttk as ttk

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    import tk.ttk as ttk
ImportError: No module named 'tk'


of course

>>> import tkinter.ttk as ttk

works

Strange, isn't it ?

[toc] | [next] | [standalone]


#106451

FromNed Batchelder <ned@nedbatchelder.com>
Date2016-04-04 08:59 -0700
Message-ID<0bf822be-6eec-4a88-acd2-e0f17cab3b30@googlegroups.com>
In reply to#106447
On Monday, April 4, 2016 at 11:31:41 AM UTC-4, ast wrote:
> hello
> 
> >>> import tkinter as tk
> >>> import tk.ttk as ttk
> 
> Traceback (most recent call last):
>   File "<pyshell#3>", line 1, in <module>
>     import tk.ttk as ttk
> ImportError: No module named 'tk'
> 
> 
> of course
> 
> >>> import tkinter.ttk as ttk
> 
> works
> 
> Strange, isn't it ?

Yes, I can see that seeming strange.  There are two things to know about
how imports work that will help explain it:

First, import statements are really just special syntax for an assignment.
When you say "import tkinter as tk", it means (in pseudocode):

    tk = __import__("tkinter")

The module named "tkinter" is sought, and when found, executed, and the
resulting module object is assigned to the name "tk".

Second, notice that "import tkinter" doesn't try to evaluate "tkinter" as
an expression. If it did, that import would raise an error, because "tkinter"
isn't defined.

So in your code, you defined the name "tk" in the first line, but that
doesn't mean the name "tk" is available for you to use in the second line.

--Ned.

[toc] | [prev] | [next] | [standalone]


#106454

FromSteven D'Aprano <steve@pearwood.info>
Date2016-04-05 02:15 +1000
Message-ID<57029328$0$1593$c3e8da3$5496439d@news.astraweb.com>
In reply to#106447
On Tue, 5 Apr 2016 01:31 am, ast wrote:

> hello
> 
>>>> import tkinter as tk
>>>> import tk.ttk as ttk
> 
> Traceback (most recent call last):
>   File "<pyshell#3>", line 1, in <module>
>     import tk.ttk as ttk
> ImportError: No module named 'tk'
> 
> 
> of course
> 
>>>> import tkinter.ttk as ttk
> 
> works
> 
> Strange, isn't it ?

No. You have to understand what the import statement does.

"import tkinter" does at least three steps:

- locate a Python file called (for example) "tkinter.py", 
  or a package "tkinter/__init__.py"
- execute that module or package file to create a module object
- create a local variable "tkinter" bound to the module object.

In pseudo-code:

# import tkinter
path = find module("tkinter")
tkinter = execute(path)


"import tkinter as tk" changes the last step:

# import tkinter as tk
path = find module("tkinter")
tk = execute(path)


Running "import tkinter as tk" doesn't change the name of the module or
package on disk. It doesn't change (say) the directory "tkinter/" to "tk/".


What happens if there is a dot in the module name?

"import tkinter.ttk as ttk" is similar to above:

- first import the package "tkinter"
- then import the submodule "ttk" inside that package.

In other words:

- locate a directory called "tkinter", containing a file called
  "__init__.py"; this is the package;
- execute that file "tkinter/__init__.py" to create a module object
- create a local variable "tkinter" bound to that module object

- then locate the module or subpackage "ttk" inside that same 
  directory;
- execute that file "tkinter/ttk.py" (for example" to create a 
  module object;
- create a local variable "ttk" bound to that module object.



So you can see why this doesn't work:


import tkinter as tk
import tk.ttk as ttk


is looking for a directory on disk called "tk", which doesn't exist. The
name "tk" is only local to your code, it doesn't rename the directory on
disk.



The real import statement is much more complicated than this, but as a
simplified description, I hope this helps.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#106469

FromTerry Reedy <tjreedy@udel.edu>
Date2016-04-04 16:46 -0400
Message-ID<mailman.38.1459802831.32530.python-list@python.org>
In reply to#106447
On 4/4/2016 11:31 AM, ast wrote:
> hello
>
>>>> import tkinter as tk
>>>> import tk.ttk as ttk
>
> Traceback (most recent call last):
>   File "<pyshell#3>", line 1, in <module>
>     import tk.ttk as ttk
> ImportError: No module named 'tk'
>
>
> of course
>
>>>> import tkinter.ttk as ttk
>
> works
>
> Strange, isn't it ?

Nope. As other said, 'import tkinter as tk' imports a module named 
'tkinter' and *in the importing modules, and only in the importing 
module*, binds the module to 'tk'.  It also caches the module in 
sys.modules under its real name, 'tkinter'.

 >>> import tkinter as tk
 >>> import sys
 >>> 'tkinter' in sys.modules
True
 >>> 'tk' in sys.modules
False

'import tk.ttk' looks for 'tk' in sys.modules, does not find it, looks 
for a module named 'tk' on disk, does not find it, and says so.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#106488

FromRustom Mody <rustompmody@gmail.com>
Date2016-04-04 21:08 -0700
Message-ID<47c51cb5-2d4b-42d3-8bf2-268720ebb4d2@googlegroups.com>
In reply to#106469
On Tuesday, April 5, 2016 at 2:17:24 AM UTC+5:30, Terry Reedy wrote:
> On 4/4/2016 11:31 AM, ast wrote:
> > hello
> >
> >>>> import tkinter as tk
> >>>> import tk.ttk as ttk
> >
> > Traceback (most recent call last):
> >   File "<pyshell#3>", line 1, in <module>
> >     import tk.ttk as ttk
> > ImportError: No module named 'tk'
> >
> >
> > of course
> >
> >>>> import tkinter.ttk as ttk
> >
> > works
> >
> > Strange, isn't it ?
> 
> Nope. As other said, 'import tkinter as tk' imports a module named 
> 'tkinter' and *in the importing modules, and only in the importing 
> module*, binds the module to 'tk'.  It also caches the module in 
> sys.modules under its real name, 'tkinter'.
> 
>  >>> import tkinter as tk
>  >>> import sys
>  >>> 'tkinter' in sys.modules
> True
>  >>> 'tk' in sys.modules
> False
> 
> 'import tk.ttk' looks for 'tk' in sys.modules, does not find it, looks 
> for a module named 'tk' on disk, does not find it, and says so.

A well-known quote comes to mind:

| There are only two hard things in Computer Science: cache invalidation and
| naming things.

eg. http://martinfowler.com/bliki/TwoHardThings.html

particularly since this seems to be in both categories :-)

[toc] | [prev] | [next] | [standalone]


#106492

FromChris Angelico <rosuav@gmail.com>
Date2016-04-05 14:23 +1000
Message-ID<mailman.52.1459830198.32530.python-list@python.org>
In reply to#106488
On Tue, Apr 5, 2016 at 2:08 PM, Rustom Mody <rustompmody@gmail.com> wrote:
>> 'import tk.ttk' looks for 'tk' in sys.modules, does not find it, looks
>> for a module named 'tk' on disk, does not find it, and says so.
>
> A well-known quote comes to mind:
>
> | There are only two hard things in Computer Science: cache invalidation and
> | naming things.
>
> eg. http://martinfowler.com/bliki/TwoHardThings.html
>
> particularly since this seems to be in both categories :-)

sys.modules isn't really a cache in that sense, though. The "hard
problem" of cache invalidation comes from the fundamental assumption
that a cache hit should be semantically identical to a cache miss;
Python's import system has fundamentally different semantics,
specifically that modules can exist independently of anything on the
disk, and modules are guaranteed to be singletons - which means that
"import decimal; decimal.getcontext().prec = 50" will affect anyone
else who uses the decimal module, because there can't be a duplicate.
(The one exception to this, where __main__ gets reimported under
another name, causes significant confusion despite being extremely
uncommon.)

If you like, you can look at sys.modules as a mandatory cache that
never records negatives and always records positives. Once an import
has succeeded, it will always be resolved from the cache, until
program termination; failed imports will always be retried. Python
dodges the cache invalidation problem by never invalidating anything
:)

ChrisA

[toc] | [prev] | [next] | [standalone]


#106493

FromRustom Mody <rustompmody@gmail.com>
Date2016-04-04 21:27 -0700
Message-ID<b707ce3a-6e9e-45dd-9f4d-2cc6c8d197a6@googlegroups.com>
In reply to#106492
On Tuesday, April 5, 2016 at 9:53:30 AM UTC+5:30, Chris Angelico wrote:
> On Tue, Apr 5, 2016 at 2:08 PM, Rustom Mody  wrote:
> >> 'import tk.ttk' looks for 'tk' in sys.modules, does not find it, looks
> >> for a module named 'tk' on disk, does not find it, and says so.
> >
> > A well-known quote comes to mind:
> >
> > | There are only two hard things in Computer Science: cache invalidation and
> > | naming things.
> >
> > eg. http://martinfowler.com/bliki/TwoHardThings.html
> >
> > particularly since this seems to be in both categories :-)
> 
> sys.modules isn't really a cache in that sense, though. The "hard
> problem" of cache invalidation comes from the fundamental assumption
> that a cache hit should be semantically identical to a cache miss;

Following looks like a cache miss to me (certainly did to the OP):

On Monday, April 4, 2016 at 9:01:41 PM UTC+5:30, ast wrote:
> hello
> 
> >>> import tkinter as tk
> >>> import tk.ttk as ttk
> 
> Traceback (most recent call last):
>   File "<pyshell#3>", line 1, in <module>
>     import tk.ttk as ttk
> ImportError: No module named 'tk'
> 

[toc] | [prev] | [next] | [standalone]


#106497

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2016-04-05 17:26 +1000
Message-ID<570368c2$0$1533$c3e8da3$5496439d@news.astraweb.com>
In reply to#106493
On Tuesday 05 April 2016 14:27, Rustom Mody wrote:

> On Tuesday, April 5, 2016 at 9:53:30 AM UTC+5:30, Chris Angelico wrote:
>> On Tue, Apr 5, 2016 at 2:08 PM, Rustom Mody  wrote:
>> >> 'import tk.ttk' looks for 'tk' in sys.modules, does not find it, looks
>> >> for a module named 'tk' on disk, does not find it, and says so.
>> >
>> > A well-known quote comes to mind:
>> >
>> > | There are only two hard things in Computer Science: cache
>> > | invalidation and naming things.
>> >
>> > eg. http://martinfowler.com/bliki/TwoHardThings.html
>> >
>> > particularly since this seems to be in both categories :-)
>> 
>> sys.modules isn't really a cache in that sense, though. The "hard
>> problem" of cache invalidation comes from the fundamental assumption
>> that a cache hit should be semantically identical to a cache miss;
> 
> Following looks like a cache miss to me (certainly did to the OP):
> 
> On Monday, April 4, 2016 at 9:01:41 PM UTC+5:30, ast wrote:
>> hello
>> 
>> >>> import tkinter as tk
>> >>> import tk.ttk as ttk
>> 
>> Traceback (most recent call last):
>>   File "<pyshell#3>", line 1, in <module>
>>     import tk.ttk as ttk
>> ImportError: No module named 'tk'


But that *miss* isn't cached -- if the OP then created a package called "tk" 
with a submodule called "ttk", and then re-ran the `import tk.ttk as ttk` 
line, the import subsystem would have picked up the newly created package 
and imported it.

I think that's the point Chris was trying to make.



-- 
Steve

[toc] | [prev] | [next] | [standalone]


#106500

FromChris Angelico <rosuav@gmail.com>
Date2016-04-05 17:47 +1000
Message-ID<mailman.57.1459842452.32530.python-list@python.org>
In reply to#106497
On Tue, Apr 5, 2016 at 5:26 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
>>> sys.modules isn't really a cache in that sense, though. The "hard
>>> problem" of cache invalidation comes from the fundamental assumption
>>> that a cache hit should be semantically identical to a cache miss;
>>
>> Following looks like a cache miss to me (certainly did to the OP):
>>
>> On Monday, April 4, 2016 at 9:01:41 PM UTC+5:30, ast wrote:
>>> hello
>>>
>>> >>> import tkinter as tk
>>> >>> import tk.ttk as ttk
>>>
>>> Traceback (most recent call last):
>>>   File "<pyshell#3>", line 1, in <module>
>>>     import tk.ttk as ttk
>>> ImportError: No module named 'tk'
>
>
> But that *miss* isn't cached -- if the OP then created a package called "tk"
> with a submodule called "ttk", and then re-ran the `import tk.ttk as ttk`
> line, the import subsystem would have picked up the newly created package
> and imported it.
>
> I think that's the point Chris was trying to make.

Not quite; that was a separate point (that negative results aren't
cached). A cache miss is when the cache doesn't have something, and
Python goes to the next source (in this case, searching the file
system). The end result should be the same in either case (you get a
module object), but in Python, a cache miss results in *actual code
execution*. Granted, you often still won't *see* any difference (your
typical module just quietly defines a bunch of stuff), but there's
still a significant semantic difference; consider what happens when
you type "import this as that" followed by "import this". The second
one is a cache hit, and it's fundamentally different in function.

Cache invalidation is all about knowing when you should *ignore* the
cached entry and go back to the file system. Python will never do
this, because the semantics are defined very differently.

ChrisA

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web