Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Basic] Modules part 2
#1
Module Creation
Python modules are just files of python code. You do not need to write special syntax to tell python you are making a module. To create a module, write some python code into a file and save as .py extension (any file is already considered a module). All names assigned at the top level of the module become its attributes and are exported for the clients to use.

If you create a module (lets call it mod1.py) with the following syntax:
def printer(var):
   print(var)
If you import mod1, you create a module with one attribute, the name printer.

module Usage
You can import this module one of 2 ways:

the import statement:
This method identifies an external file to be loaded. It creates mod1 as a variable in the script. mod1 references the module object after it is done being loaded. We must then use the module name to fetch its attributes.
import mod1
mod1.printer('test')
the from statement:
The from statement copies the names from one file over to another scope. It allows us to use the copied namess directly in the script wihtout going through the module. However printer has less meaning to a reader than mod1.printer. Also it has the potential to silently overwrite names, if you imported names that that have the same names as  existing variables in your scope. this peoblem does not occur in the import statement, as you always go through the module's name to get its contents.
from mod1 import printer
printer('test')
the from * statement:
The previous applies here also, except this method copies all names in the module into the importing scope. It essentially collapses one namespace into another. Here is a tutorial on why this is NOT preferred.
from mod1 import *
printer('test)
All of these are valid to import a module. The net effect of the from * statements though is less typing. However it is shunned upon as it floods the namespace. One example would be if you had a ton of modules to import and all of them used the from * statement. Where does printer() comes from, mod1? mod2? mod3? etc. etc.

Imports loaded once
AS state in part 1, modules are loaded and run of the first imoport or from, and only the first. Python does it once per file, once per process. As a result you could use it to initialze variables:
lets say we created a module mod2.py
print('test')
var = 1
>>> import mod2
test
>>> mod2.var
1
>>> mod2.var = 2
>>> import mod2
>>> mod2.var
2
mod2.var is still 2 as the second import just fetched the already loaded module. If however you wanted it to be reran, you could use imp.reload(). In python, you can access the attributes of any object that has attributes using the qualification syntax object.attribute.

import and from are assignemnts
As wtih def, import and from are executable statements, not compile-time declarations. They could be nested in if tests, in function defs, etc. They are not ran until Python reaches them while executing your program. 
an example would be:
import sys

if sys.platform[:3] == 'win':
	import msvcrt
	def getchar():
		...
else:
	import termios
	def getchar():
		...
this program imports msvcrt if the platform is windows, or else imports termios. Where msvcrt causes an import error on linux for example. With more code not shown, you could define getchar() one way if windows, or another way if linux, etc.

Module Namespaces
lets call this module mod3.py
print('loading')
import sys

name = 20

def func():
	pass

class Klass:
	pass 
print('done loading')
"name" is an attribute of mod3, which we refer to outside of the module as
mod3.name
The "name" variable is also global variable to any other code inside mod3.py.
If you import this module the two print statements execute at import time:
>>> import mod3
loading
done loading
>>> 
Once done loading, it's scope becomes an attribute namespace in the module object we get back from import. We can access attributes in this namespace by qualifying them with the name of the enclosing module. 
>>> mod3.sys
<module 'sys' (built-in)>
>>> mod3.name
20
>>> mod3.func
<function func at 0x7fbbcda49d40>
>>> mod3.Klass
<class 'mod3.Klass'>
>>> 
Internally, module namespaces are stored as dictionary objects, to view the object
>>> list(mod3.__dict__.keys())
['__builtins__', '__file__', 'func', '__name__', 'Klass', '__package__', 'name', '__initializing__', '__cached__', '__loader__', 'sys', '__doc__']
>>> 
Python adds some namespace for us, like:
__file__ is the  name of the file the module was loaded from
__name__ gives its name as known to importers (without the .py ext and directory path)
>>> mod3.__file__
'./mod3.py'
>>> mod3.__name__
'mod3'
>>> 
reload
imp.reload forces an already loaded module's code to be reloaded and rerun.

lets make a module called mod4.py and in it:
msg = 'first'

def printer():
	print(msg)
now go to the interpreter and import that module. 
>>> import mod4
>>> mod4.printer()
first
>>> mod4.msg
'first'
>>>
now keep the interpreter open (this signifies a program that is still running) and modify the module, to something like:
msg = 'second'

def printer():
	print(msg)
	
and save and back to the interpreter:
>>> mod4.printer()
first
printer() still returns the old data, so to get its current, we have to reload that module
>>> from imp import reload
>>> reload(mod4)
<module 'mod4' from './mod4.py'>
>>> mod4.printer()
second
Go to Modules part 3
Go to Modules part 1
Recommended Tutorials:
#2
-
Recommended Tutorials:


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Basic] Modules part 3 metulburr 0 6,333 Sep-05-2016, 09:11 PM
Last Post: metulburr
  [Basic] Modules part 1 metulburr 0 9,822 Sep-05-2016, 09:10 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020