summaryrefslogtreecommitdiff
path: root/advanced_python/modules.rst
blob: f3df6767262d882f0ad295d9bf27dc32d30f5498 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
Using Python modules
====================

We shall, in this section, see how to run Python scripts from the command
line, and more details about importing modules. 

Let us create a simple python script to print hello world. Open your text
editor and type the following, and save the script as ``hello.py``. 

::

    print "Hello world!"

Until now we have been running scripts from inside IPython, using

::

    %run -i hello.py

But, as we know, IPython is just an advanced interpreter and it is not
mandatory that every one who wants to run your program has IPython
installed. 

So, the right method to run the script, would be to run it using the Python
interpreter. Open the terminal and navigate to the directory where
``hello.py`` is saved. 

Then run the script by saying, 
::

    python hello.py

The script is executed and the string ``Hello World!`` has been printed. 

Now let us run a script that plots a simple sine curve in the range -2pi to
2pi, using Python, instead of running it from within IPython. 

Type the following lines and save it in ``sine_plot.py`` file. 

::

    x = linspace(-2*pi, 2*pi, 100)
    plot(x, sin(x))
    show()

Now let us run sine_plot.py as a python script.

::

    python sine_plot.py

Do we get the plot? No! All we get is error messages. Python complains that
``linspace`` isn't defined. What happened? Let us try to run the same
script from within IPython. Start IPython, with the ``-pylab`` argument and
run the script. It works!

What is going on, here? IPython when started with the ``-pylab`` option, is
importing a whole set of functionality for us to work with, without
bothering about importing etc. 

Let us now try to fix the problem by importing ``linspace``. 

Let's add the following line as the first line in the script. 

::

    from scipy import *

Now let us run the script again,

::

    python sine_plot.py

Now we get an error, that says ``plot`` is not defined. Let's edit the file
and import this from pylab. Let's add the following line, as the second
line of our script. 

::

    from pylab import *

And run the script,

::

    python sine_plot.py

Yes! it worked. So what did we do?

We actually imported the required functions and keywords, using ``import``.
By using the * , we are asking python to import everything from the
``scipy`` and ``pylab`` modules. This isn't a good practice, as 
1. it imports a lot of unnecessary things
2. the two modules may have functions with the same name, which would
  cause a conflict. 

One of the ways out is to import only the stuff that we need, explicitly. 

Let us modify sine_plot.py by replacing the import statements with the
following lines. 

::

    from scipy import linspace, pi, sin
    from pylab import plot, show

Now let us try running the code again as,

::

    python show_plot.py

As expected, this works. But, once the number of functions that you need to
import increases, this is slightly inconvenient. Also, you cannot use
functions with the same name, from different modules. To overcome this,
there's another method. 

We could just import the modules as it is, and use the functions or other
objects as a part of those modules. Change the import lines, to the
following. 

::

    import scipy
    import pylab

Now, replace ``pi`` with ``scipy.pi``. Similarly, for ``sin`` and
``linspace``. Replace ``plot`` and ``show`` with ``pylab.plot`` and
``pylab.show``, respectively. 

Now, run the file and see that we get the output, as expected. 

We have learned how to import from modules, but what exactly is a module?
How is one written? 

A module is simply a Python script containing the definitions and
statements, which can be imported. So, it is very easy to create your own
modules. You just need to stick in all your definitions into your python
file and put the file in your current directory. 

When importing, Python searches the locations present in a variable called
the Python path. So, our module file should be present in one of the
locations in the Python path. The first location to be searched is the
current directory of the script being run. So, having our module file in
the current working directory, is the simplest way to allow it to be used
as a module and import things from it. 

Python has a very rich standard library of modules. It is very extensive,
offering a wide range of facilities. Some of the standard modules are,

for Math: math, random
for Internet access: urllib2, smtplib
for System, Command line arguments: sys
for Operating system interface: os
for regular expressions: re
for compression: gzip, zipfile, tarfile
And there are lot more.

Find more information at Python Library reference,
``http://docs.python.org/library/``

There are a lot of other modules like pylab, scipy, Mayavi, etc which
are not part of the standard Python library.

This brings us to the end of our discussion on modules and running scripts
from the command line. 

Writing modules
===============

In this section we shall look at writing modules, in some more detail.
Often we will have to reuse the code that we have previously written. We do
that by writing functions. Functions can then be put into modules, and
imported as and when required. 

Let us first write a function that computes the gcd of two numbers and save it in a script.

::

    def gcd(a, b):
        while b:
            a, b = b, a%b
        return a

Now, we shall write a test function in the script that tests the gcd function, to see if it works. 

::

    if gcd(40, 12) == 4 and gcd(12, 13) == 1:
        print "Everything OK"
    else:
        print "The GCD function is wrong"

Let us save the file as gcd_script.py in ``/home/fossee/gcd_script.py`` and
run it. 

::

    $ python /home/fossee/gcd_script.py

We can see that the script is executed and everything is fine.

What if we want to use the gcd function in some of our other scripts. This
is also possible since every python file can be used as a module.

But first, we shall understand what happens when you import a module.

Open IPython and type

::

    import sys
    sys.path

This is a list of locations where python searches for a module when it
encounters an import statement. Hence, when we just did ``import sys``,
python searches for a file named ``sys.py`` or a folder named ``sys`` in
all these locations one by one, until it finds one. We can place our script
in any one of these locations and import it.

The first item in the list is an empty string which means the current
working directory is also searched.

Alternatively, we can also import the module if we are working in same
directory where the script exists.

Since we are in /home/fossee, we can simply do

::

    import gcd_script
    
We can see that the gcd_script is imported. But the test code that we added
at the end of the file is also executed.

But we want the test code to be executed only when the file is run as a
python script and not when it is imported.

This is possible by using ``__name__`` variable.


Go to the file and add

::

    if __name__ == "__main__":
        
before the test code and indent the test code.

Let us first run the code.

::

    $ python gcd_script.py

We can see that the test runs successfully.

Now we shall import the file

::
    
    import gcd_script

We see that now the test code is not executed.

The ``__name__`` variable is local to every module and it is equal to
``__main__`` only when the file is run as a script. Hence, all the code
that goes in to the if block, ``if __name__ == "__main__":`` is executed
only when the file is run as a python script.

.. 
   Local Variables:
   mode: rst
   indent-tabs-mode: nil
   sentence-end-double-space: nil
   fill-column: 75
   End: