For those who patiently read each line

Geert-Jan Van den Bogaerde gvdbogae at vub.ac.be
Tue Aug 13 14:42:26 CEST 2002


On Tue, 2002-08-13 at 12:01, snodx at hotmail.com wrote:

[snipped]

> 
> CoDe BlOcK 1
> 
> (4 arguments are passed to this Python script "username", "password", "to"
>  and "text"
> 
> #!/usr/bin/python
> 
> import os, string, sys, urllib                                      #LiNe 1

This imports the modules os, string, sys and urllib, which are all part
of python's standard library.

Instread of analysing the source code in these modules as you have done
below, you might benefit from simple consulting the standard library
documentation for python 1.5 for these modules to get a high-lever view
of what they do: http://www.python.org/doc/1.5.2p2/lib/lib.html

> 
> HOST = "localhost"                                                  #LiNe 2
> PORT = 13013                                                        #LiNe 3
> USERNAME = "tester"                                                 #LiNe 4
> PASSWORD = "foobar"                                                 #LiNe 5

Initialize some global variables. This should be obvious. HOST, USERNAME
and PASSWORD are indeed string objects (as they are being assigned
string literals), while PORT is an integer (being assigned an integer
literal).

> 
> NUMBERS = "~/.sendsms.dat"                                          #LiNe 6
> 

This sets the location of a data file (judging from code below, it
contains a mapping from names to phone numbers using a plain text
format). The tilde ("~") character is a UNIX shorthand for the user's
home directory. The leading dot (".") in the filename indicates a hidden
file.

> def is_a_phone_number(str):                                         #LiNe 7
>     if not str:                                                     #LiNe 8
>         return 0                                                    #LiNe 9
>     for c in str:                                                   #LiNe 10
>         if not c in "0123456789+- ":                                #LiNe 11
>             return 0                                                #LiNe 12
>     return 1                                                        #LiNe 13

This function tests whether the str parameter contains only the
characters 0 through 9, + or -. It returns 0 (which in a boolean context
evaluates to false) if the string contains any other characters, and 1
(which evaluates to a boolean true) if it doesn't.

> 
> def recipient(arg):                                                 #LiNe 14
>     if is_a_phone_number(arg):                                      #LiNe 15
>         return arg                                                  #LiNe 16
>     f = open(os.path.expanduser(NUMBERS), "r")                      #LiNe 17
>     arg = string.lower(arg)                                         #LiNe 18
>     number = None                                                   #LiNe 19
>     for line in f.readlines():                                      #LiNe 20
>         parts = string.split(line)                                  #LiNe 21
>         if len(parts) == 2 and string.lower(parts[0]) == arg:       #LiNe 22
>             number = parts[1]                                       #LiNe 23
>             break                                                   #LiNe 24
>     f.close()                                                       #LiNe 25
>     if number:                                                      #LiNe 26
>         return number                                               #LiNe 27
>     print "Unknown recipient", arg                                  #LiNe 28
>     sys.exit(1)                                                     #LiNe 29

This function looks up the phone number of the recipient named in the
arg parameter. 

First the function tests whether the arg parameter is already in the
format of a phone number, in which case nothing further needs to be done
and the parameter is returned as the value of the function.

If this isn't the case the function opens the filename assigned before
to the NUMBER variable in read-only mode (the "r" argument to open). The
open function is a built-in python function and is documented here:
http://www.python.org/doc/1.5.2p2/lib/built-in-funcs.html

The arg arguments is then converted to lowercase using the "lower"
method from the string module.

The number value which is used later to store the phone number that
corresponds to our "arg" parameter is set to None, which serves as a
NULL value. None will evaluate to false in a boolean context.

The open function returned a file object which was assigned to the
variable f. File objects have a number of methods for reading and
writing, documented here:
http://www.python.org/doc/1.5.2p2/lib/typesother.html#SECTION004179000000000000000

In this case the readline object returns a list where each entry is one
line from the file. The for-loop iterates over the elements of this
list, assigning each line in turn to the variable "line".

The line is then split on whitespace using the "split" function from the
string module:
http://www.python.org/doc/1.5.2p2/lib/module-string.html

The return value of split is a list containing the substrings, which is
assigned to parts.

The length of this list is tested with the built-in function len (see
the built-in function docs). The file appears to map names to phone
numbers in a format such as this:

<name><whitespace><phone number>

For example:

snodx 123456789
geert-jan 98765432
[and so on]

(<whitespace> here could be spaces or tables)

If parts[0] (which should contain the "snodx" on the first iteration in
our example) is equal to the arg parameter, then the corresponding phone
number (parts[1]) is assigned to the variable number. The break
statement terminates the "for" loop.

f.close() closes our numbers file.

Next the function tests whether number was assigned a value different
from None (or any expression evaluating to a boolean false), and returns
the phone number if so.

If no number was found, the exit function of the sys module is used to
terminate the program with an exit status of 1.

> 
> def sendsms():                                                      #LiNe 30
>     to = urllib.quote_plus(recipient(sys.argv[1]))                  #LiNe 31
>     text = urllib.quote_plus(string.join(sys.argv[2:], " "))        #LiNe 32
>     url="http://%s:%d/cgi-bin/sendsms?username=%s&password=%s&to=%s&text=%s" \  #LiNe 33
>         % (HOST, PORT, USERNAME, PASSWORD, to, text)                            #LiNe 34
>     f = urllib.urlopen(url)                                                     #LiNe 35
>     print f.read()                                                              #LiNe 36
>     f.close()                                                                   #LiNe 37

The urllib documentation should clear up what happens here: it opens a
URL containing some of the parameters given to the script (the
%-operator works like the printf family of functions in C) and print it
to standard output. 

Consult the standard library docs for the meaning of urrlib.quote_plus
and string.join, the short descriptions there should be quite
sufficient, no need to go analyzing the full source code to these
modules.

> 
> if __name__ == "__main__":                                                      #LiNe 38
>     sendsms()                                                                   #LiNe 39
> 

The __name__ variable is set to the value "__main__" by python if the
script was invoked directly (and not imported from another script as a
module).

Just one more note:

StOp It WiTh ThE LaMe CaPiTaLiZaTiOn!

kind regards,

Geert-Jan





More information about the Python-list mailing list