Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespaces with Module Imports

Tags:

I am learning Python and am still a beginner, although I have been studying it for about a year now. I am trying to write a module of functions which is called within a main module. Each of the functions in the called module needs the math module to run. I am wondering if there is a way to do this without importing the math module inside the called module. Here is what I have:

main.py:

from math import * import module1  def wow():      print pi   wow() module1.cool() 

module1.py:

def cool():      print pi 

When running main.py I get:

3.14159265359  Traceback (most recent call last):   File "Z:\Python\main.py", line 10, in <module>     module1.cool()   File "Z:\Python\module1.py", line 3, in cool     print pi NameError: global name 'pi' is not defined 

What I'm having a hard time understanding is why I get a name error when running main.py. I know that the variable pi becomes global to the main module upon import because wow can access it. I also know that cool becomes global to the main module upon import because I can print module1.cool and get <function cool at 0x02B11AF0>. So since cool is inside the global namespace of the main module, shouldn't the program first look inside the function cool for the variable pi, and then when it doesn't find it there, look inside main module for the variable pi and find it there?

The only way to get around this that I know of is to import the math module inside module1.py. I don't like the idea of that, though because it makes things more complicated and I am a fan of nice, simple code. I feel like I am close to grasping namespaces, but need help on this one. Thanks.

like image 886
SpencerAAA Avatar asked Apr 08 '13 22:04

SpencerAAA


People also ask

How do you import a namespace in Python?

Importing is a way of pulling a name from somewhere else into the desired namespace. To refer to a variable, function, or class in Python one of the following must be true: The name is in the Python built-in namespace. The name is the current module's global namespace.

What is a module namespace?

In Python-speak, modules are a namespace—a place where names are created. And names that live in a module are called its attributes. Technically, modules correspond to files, and Python creates a module object to contain all the names defined in the file; but in simple terms, modules are just namespaces.

Which command creates a separate namespace for the imported module S?

import <module_name> Thus, a module creates a separate namespace, as already noted. The statement import <module_name> only places <module_name> in the caller's symbol table. The objects that are defined in the module remain in the module's private symbol table.


2 Answers

As the traceback shows, the problem isn't in main.py, but in module1.py:

Traceback (most recent call last):   File "Z:\Python\main.py", line 10, in <module>     module1.cool()   File "Z:\Python\module1.py", line 3, in cool     print pi NameError: global name 'pi' is not defined 

In other words, in module1, there is no global name pi, because you haven't imported it there. When you do from math import * in main.py, that just imports everything from the math module's namespace into the main module's namespace, not into every module's namespace.

I think the key thing you're missing here is that each module has its own "global" namespace. This can be a bit confusing at first, because in languages like C, there's a single global namespace shared by all extern variables and functions. But once you get past that assumption, the Python way makes perfect sense.

So, if you want to use pi from module1, you have to do the from math import * in module1.py. (Or you could find some other way to inject it—for example, module1.py could do from main import *, or main.py could do module1.pi = pi, etc. Or you could cram pi into the magic builtins/__builtin__ module, or use various other tricks. But the obvious solution is to do the import where you want it imported.)


As a side note, you usually don't want to do from foo import * anywhere except the interactive interpreter or, occasionally, the top-level script. There are exceptions (e.g., a few modules are explicitly designed to be used that way), but the rule of thumb is to either import foo or use a limited from foo import bar, baz.

like image 54
abarnert Avatar answered Sep 19 '22 06:09

abarnert


"Explicit is better than implicit" is a design decision that was made by the creators of Python (launch python and run import this).

Therefore, when you run module1.cool(), Python will not look for the undefined pi in the main module.


You'll have to import the math module in explicitly whenever you want to use it - that's just how Python works.

Also, you should avoid from X import *-style imports, that's bad practice too. Here, you could do: from math import pi.

like image 28
Thomas Orozco Avatar answered Sep 22 '22 06:09

Thomas Orozco