Tuesday, February 9, 2010

Writing Your Own Python Modules

Extending the Python Language with your own Modules


One of the best bits about Python is the extensive catalogue of modules that are around, and free, to extend the power and functionality of the language. Sometimes, however, it is necessary to create your own - perhaps because a particular feature isn't available in the standard build, perhaps a new technology has arrived that you wish to write an API for, or perhaps you are writing a large application where the breaking up of code is necessary for it to remain flexible and unbloated. Whatever your reasoning, this article serves as a basic introduction to module creation in Python. It covers both procedural and Object Orientated programming, but will not go into detailed specifics of either. However, it will give enough information for you to be able to begin developing your own "add-ons" to the Python language.

I'm using Python 2.6 so there will be slight differences if you are using another version.

Brief Overview of Modules in Python


Modules in Python are imported using the "import" statement.
CODE :
__________________________________________________________________________
import re
__________________________________________________________________________
That, for example, imports "re" - the regex module - into the document. The functions and classes belonging to "re" can be accessed like so:
CODE :
__________________________________________________________________________
import re
re.function(....)
__________________________________________________________________________

Modules on my system (Linux Xubuntu) are stored in /usr/lib/python2.6/
It'll be different on Windows - obviously - and may be on Mac and other Linux distros. You'll have to do some searching. On a *nix system, using this command should help you locate them:
CODE :
__________________________________________________________________________
locate urllib2
__________________________________________________________________________

However you don't have to stick all your modules in there, if the python interpretter can't find your module there, it'll look in the current working directory.
Modules have to end with .py too.

Your First Module


First I'm going to create two files: "firstmod.py" - which will contain the actual module - and "test.py" - with which we will test it (this could also be replaced by the Python console).

CODE :
__________________________________________________________________________
# firstmod.py

def doSomething(a,b):
c = a + b + 5
return c
__________________________________________________________________________

CODE :
__________________________________________________________________________
# test.py
import firstmod
print firstmod.doSomething(5,6)
__________________________________________________________________________

When we execute test.py, we get 16.
The code is pretty self explanatory. Now I'm going to do something a little different.
CODE :
__________________________________________________________________________
#test.py
from firstmod import doSomething
print doSomething(4,9)
__________________________________________________________________________

This time, instead of importing the entire module (which, admittedly, in this case is still only the one function), we are just importing that doSomething function. However, there's another difference. We're not accessing that function through the module itself but instead as we would any other function that we have created. That can be useful if you only want to access the one function, and don't want to have to type out a long module name each time you want to use it.
Another way of using the "from ... import ..." statement is with the wildcard '*'. Now you should know that that means everything, and that's exactly what it does. Import everything. In most cases you shouldn't do that, but there are cases when it is useful - especially when doing GUI programming, should you want to.
CODE :
__________________________________________________________________________
#test.py
from firstmod import *
print doSomething(2,6)
__________________________________________________________________________
See? Pretty simple.

[h3]Initialisation[/h3]
You may, for some reason, want to execute a few lines of code as soon as your module is imported. What for, I don't know, but perhaps there's an application. To do this, well.. just write that code in there.
CODE :
__________________________________________________________________________
# firstmod.py
def doSomething(a,b):
c = a + b + 5
return c

print "Initialised."
a = 5
__________________________________________________________________________

Okay, so I've made it print out "Initialised" and have set the variable "a" to 5. Now what does this look like when I import it?
I'll show you the output from the Python console.
CODE :
__________________________________________________________________________
>>> import firstmod
Initialised.
>>> print firstmod.a
5
>>> print a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
__________________________________________________________________________

That's pretty important to note. When you set a global variable in a module as I did above, you can access that variable as you would a function.
As expected, it works the same as functions when specifically imported:
CODE :
__________________________________________________________________________
>>> from firstmod import *
Initialised.
>>> print a
5
__________________________________________________________________________

However, here's a little quirk:
CODE :
__________________________________________________________________________
>>> from firstmod import doSomething
Initialised.
>>> print a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
>>> print firstmod.a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'firstmod' is not defined
__________________________________________________________________________

Hopefully those output snippets will help you understand how things work, I think that they explain better than I could, anyway.

[h3]Documentation[/h3]
Presumably at some point in your Python programming lives you will have used the help function. What you may not know is that the documentation for each module is in fact built in to the module.
Here's some code that will explain how it works.
CODE :
__________________________________________________________________________
# firstmod.py
"""This is an introduction to the firstmod module. It tells the user how to use the module as a whole, may give code snippets and generally give an idea of what the module does and how it does it. This can, and nearly always does, run over multiple lines."""
def doSomething(a,b):
"""This explains what this particular module does, so for example, in this circumstance I might say:
doSomething returns the sum of the two arguments with 5 added on."""
c = a + b + 5
return c
__________________________________________________________________________

Now try importing your module in the Python console, and typing "help(firstmod)".

[h3]Object Orientated[/h3]
Object Orientated programming is a tricky subject and can take a while to grasp completely. It's something that I like, but am wary of, and would advise anyone to read a lot about it before just jumping in.
I think the best way to teach this bit would be to actually create a working module - so that's what we'll do. We're going to write a 'toggle' variable: a variable with two specific positions and a function that switches between them. The best example is "True" or "False". Yep, they already have the boolean variable. Yep, you probably will never use this (though I've actually used it occasionally). Yep, it's pretty simple and a good learning script. So let's get started.

You can look at the full, finished code here: http://pastebin.com/m64220b4b
We won't be writing that much but feel free to add to the module if you want.

First of all I'm going to create a single file, "toggle.py". I will use the Python console for importing the module, etc.
Inside that, we'll have the class "toggle". Let's write some code.
CODE :
__________________________________________________________________________
# toggle.py
"""Toggle variable module"""
class toggle(object):
"""Toggle object with 2 possible values"""
def __init__(self, first, second):
"""This is executed as soon as the class is loaded"""
self.statements = first,second
self.position = 0
__________________________________________________________________________

Right, I'm going to stop there and explain a little. From now on, however, we'll be adding code to that class (not function), unless I state otherwise.
If we were to import this code and use it, we'd do it like this:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
__________________________________________________________________________

The self in self.statements and self.position refers to the class itself. I won't explain it in detail because that'd involve basically explaining OOP, which would take another article. The self.statements variable is a tuple. It is assigned the variables passed to the __init__ function.

Okay, let's give this some functionality - we're going to make the object return a value when printed. Try this:
CODE :
__________________________________________________________________________
import toggle
t = toggle.toggle()
print t
__________________________________________________________________________

Now wouldn't it be nicer if it returned the current value then, rather than some weird value? Python is great in the way it lets you manipulate the language like that, here's how we'd do it:
CODE :
__________________________________________________________________________
# remember, we're adding a new function to the class here
def __str__(self):
"""Returns the current value"""
return str(self.statements[self.position])
__________________________________________________________________________

Now try the previous code and see what you get. Great, eh?
Currently though, you can't change the value. I'm going to introduce a toggle() function now.

CODE :
__________________________________________________________________________
def toggle(self):
"""Switch value, returns new value"""
if self.position == 0:
self.position = 1
else:
self.position = 0
return self.statements[self.position]
__________________________________________________________________________

Pretty self explanatory really. Let's try using it now:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
>>> print t
option1
>>> t.toggle()
'option2'
>>> print t
option2
__________________________________________________________________________

[h3]Conclusion[/h3]
There we have it. That's your first basic module. There's a lot more you can do too and I encourage you to read up more on the subject. Writing modules is great fun, especially if you know Perl or another scripting language, and can port some modules over.
If you want to try out your skills writing modules, why not consider writing an IRC bot module? Or a noughts and crosses game, perhaps? There are plenty of applications.

Here's an old module I wrote for writing IRC bots. It isn't complete and it is probably pretty poorly coded in parts - I haven't looked at it for a while now. I'm not saying that it's perfect at all, but why don't you fix some problems it has? It definitely needs some regexs in there - message parsing has been done by hand :/
http://pastebin.com/m4e121ebf

Good luck, thanks for reading and have fun!
If there are any errors in the article, please leave a comment (or PM me if the comments system is down). Feel free to leave your opinions. :)
~thedotmaster

No comments:

Post a Comment

try to make something then you never be lost

+++

Share |

"make something then You never be lost"

wibiya widget