[Tutor] Looking for peer review
Joel Ricker
joel@prettyhipprogramming.com
Thu, 11 Jul 2002 12:48:53 -0400
This is a multi-part message in MIME format.
------=_NextPart_000_001E_01C228D9.50324040
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Below is a program that I've been working on that reports changes in =
ipaddresses. I work in a retail store and we have two other stores =
about an hour drive away. Once a week the owner comes down and makes =
backups of our inventory and gives us copies of inventories from the =
other two stores. The owner decided to set us all up with a broadband =
connection and use PCAnywhere to connect and make changes to the system.
Of course the problem is that the ip addresses of all the connections =
will change at least once a day. When he complained about having to =
call us for the ip address whenever he wanted to login, I knew Python =
would do the trick :)
The purpose of this program is to check the ip address periodically and =
if it changes, connect to an smtp server and send an e-mail reporting =
the change. That way, he should always have the current ip address of =
our system.
I'd like for everyone to critique my program and give me any pointers on =
making it better and helping me become a better python programmer. This =
is my first "real" python program -- something that's not throw away =
code and that will be used by someone else.=20
## ipwatch.py
import socket, getopt, sys, time, smtplib
def usage(evalue):
''' Show instructions and pass exit evalue '''
=20
print
print "ipwatch by Joel Ricker (joel@prettyhipprogramming.com)"
print "Monitors current machines IP address and reports any changes =
by e-mail."
print =20
print "Usage:python ipwatch.py --help | --to <to address> --from =
<from address> "
print "[--smtp <smtp address>] [--port <port>] [--user <username>] =
[--pass <password>] [--wait <minutes>]" =20
print
print "Options:"
print "\t--help\tShows this help message."
print "\t--to\tE-mail address to send reports to."
print "\t--from\tE-mail address to set as reply to."
print "\t--smtp\tAddress of smtp server to send mail through."
print "\t\tDefaults to localhost."
print "\t--port\tPort address of smtp server. Defaults to 25"
print "\t--user\tIf smtp server requires authorization, the username =
to login as."
print "\t--pass\tIf smtp server requires authorization, the password =
to login as."
print "\t--wait\tTime in minutes to wait between ip address checks."
=20
sys.exit(evalue) =20
=20
def get_addy():
try:
addy =3D socket.gethostbyname(socket.getfqdn())
except:
sys.stderr.write("Socket Error: Couldn't aquire address of this =
machine.")
sys.exit(2)
else:
return addy
=20
def main(): =20
# Load the file that holds the current ip address of this machine =
try:
f =3D file("ipwatch.dat", "r")
addy =3D f.readline()
f.close()
except:
f =3D file("ipwatch.dat", "w")
addy =3D get_addy() =20
f.write(addy)
f.close() =20
=20
# Load command line options
try:
opts, args =3D getopt.getopt(sys.argv[1:], "hs:p:t:f:u:p:w:",
["help", "smtp=3D", "port=3D", =
"to=3D", "from=3D", "user=3D", "pass=3D", "wait=3D"])
except getopt.GetoptError:
# print help information and exit:
usage(2) =20
else:
if not len(opts):
usage(2) =20
smtpaddy =3D 'localhost'
port =3D 25
fromwho =3D None
towho =3D None
user =3D None
password =3D None
wait =3D None
print opts
print args
# Process options
for o, a in opts:
=20
# Help - prints out the instructions for use
if o in ("-h", "--help"):
usage(0) =20
=20
# SMTP - the address of the smtp server to send the e-mail =
through
if o in ("-s", "--smtp"):
smtpaddy =3D a
# Port - port
if o in ("-p", "--port"):
port =3D a
# To - the address to send the e-mail to
if o in ("-t", "--to"):
towho =3D a
# From - the reply address
if o in ("-f", "--from"):
fromwho =3D a
=20
# Username - the username to login as if required
if o in ("-u", "--user"):
user =3D a
=20
# Password - the password of the smtp server if required
if o in ("-p", "--pass"):
password =3D a
# Time - amount of time in minutes to wait
if o in ("-w", "--wait"): =20
wait =3D int(a) * 60 =20
# Check for required and valid command-line options
if towho is None:
sys.stderr.write("To address required.")
usage(2) =20
if fromwho is None:
sys.stderr.write("From address required.")
usage(2) =20
if wait < 300:
sys.stderr.write("Invalid wait value.")
usage(2)
=20
=20
=20
# Now we loop, checking the current address of the machine against =
the address stored
# in the file. If we have a new address, we store that address in =
the file and report
# the new address by e-mail. We're depending on Window's shutdown =
signal to stop
# properly
while (1):
newaddy =3D get_addy()
if addy !=3D newaddy:
print "New addy: ", newaddy
f =3D open("ipwatch.dat", "w")
f.write(newaddy)
f.close()
=20
try:
s =3D smtplib.connect(smtpaddy, port)
if user is not None: =20
try:
s.login(user, password)
except SMTPAuthenticationError:
sys.stderr.write("Error logging into SMTP =
server. Check username and password and re-attempt")
s.sendmail(towho, fromwho, newaddy)
s.quit()
=20
except SMTPException, reason:
sys.stderr.write("SMTP Error: %s", (reason))
addy =3D newaddy
print "The current address is", addy
time.sleep(wait) =20
=20
=20
if __name__ =3D=3D "__main__":
main()
=20
Thanks
Joel
------=_NextPart_000_001E_01C228D9.50324040
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2479.6" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>Below is a program that I've been =
working on that=20
reports changes in ipaddresses. I work in a retail store and we =
have two=20
other stores about an hour drive away. Once a week the owner comes =
down=20
and makes backups of our inventory and gives us copies of inventories =
from the=20
other two stores. The owner decided to set us all up with a =
broadband=20
connection and use PCAnywhere to connect and make changes to the=20
system.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Of course the problem is that the ip =
addresses of=20
all the connections will change at least once a day. When he =
complained=20
about having to call us for the ip address whenever he wanted to login, =
I knew=20
Python would do the trick :)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The purpose of this program is to check =
the ip=20
address periodically and if it changes, connect to an smtp server and =
send an=20
e-mail reporting the change. That way, he should always have the =
current=20
ip address of our system.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>I'd like for everyone to critique my =
program and=20
give me any pointers on making it better and helping me become a better =
python=20
programmer. This is my first "real" python program -- something =
that's not=20
throw away code and that will be used by someone =
else. </FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>## ipwatch.py</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>import socket, getopt, sys, time,=20
smtplib</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>def =
usage(evalue):<BR> ''' Show=20
instructions and pass exit evalue '''<BR> =20
<BR> print<BR> print "ipwatch by =
Joel Ricker=20
(<A=20
href=3D"mailto:joel@prettyhipprogramming.com">joel@prettyhipprogramming.c=
om</A>)"<BR> =20
print "Monitors current machines IP address and reports any changes by=20
e-mail."<BR> print =
<BR> =20
print "Usage:python ipwatch.py --help | --to <to address> --from =
<from=20
address> "<BR> print "[--smtp <smtp address>] =
[--port=20
<port>] [--user <username>] [--pass <password>] =
[--wait=20
<minutes>]" <BR> =20
print<BR> print "Options:"<BR> print =
"\t--help\tShows this help message."<BR> print =
"\t--to\tE-mail=20
address to send reports to."<BR> print =
"\t--from\tE-mail=20
address to set as reply to."<BR> print =
"\t--smtp\tAddress of=20
smtp server to send mail through."<BR> print =
"\t\tDefaults to=20
localhost."<BR> print "\t--port\tPort address of smtp =
server.=20
Defaults to 25"<BR> print "\t--user\tIf smtp server =
requires=20
authorization, the username to login as."<BR> print=20
"\t--pass\tIf smtp server requires authorization, the password to login=20
as."<BR> print "\t--wait\tTime in minutes to wait =
between ip=20
address checks."<BR> <BR> =20
sys.exit(evalue) <BR> =
</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>def get_addy():<BR> =20
try:<BR> addy =3D=20
socket.gethostbyname(socket.getfqdn())<BR> =20
except:<BR> =
sys.stderr.write("Socket=20
Error: Couldn't aquire address of this=20
machine.")<BR> =20
sys.exit(2)<BR> =20
else:<BR> return=20
addy<BR> <BR>def=20
main(): </FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2> # Load the file that =
holds the=20
current ip address of this machine =
<BR> =20
try:<BR> f =3D =
file("ipwatch.dat",=20
"r")<BR> addy =3D=20
f.readline()<BR> =20
f.close()<BR> =20
except:<BR> f =3D =
file("ipwatch.dat",=20
"w")<BR> addy =3D=20
get_addy() =20
<BR> =20
f.write(addy)<BR> =20
f.close() =
<BR> =20
<BR> # Load command line options<BR> =
try:<BR> opts, args =3D=20
getopt.getopt(sys.argv[1:],=20
"hs:p:t:f:u:p:w:",<BR> &nb=
sp; &nbs=
p;  =
; =20
["help", "smtp=3D", "port=3D", "to=3D", "from=3D", "user=3D", "pass=3D", =
"wait=3D"])<BR> except=20
getopt.GetoptError:<BR> # =
print help=20
information and exit:<BR> =20
usage(2) =
<BR> =20
else:<BR> if not=20
len(opts):<BR>  =
; =20
usage(2)  =
;=20
</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2> smtpaddy =3D=20
'localhost'<BR> port =3D 25<BR> =
fromwho =3D=20
None<BR> towho =3D None<BR> user =3D =
None<BR> password =3D None<BR> wait =
=3D=20
None</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2> print =
opts<BR> =20
print args<BR> # Process options<BR> =
for o,=20
a in opts:<BR> =20
<BR> # Help - prints out the=20
instructions for use<BR> if o =
in=20
("-h",=20
"--help"):<BR>  =
; =20
usage(0)  =
;=20
<BR> =20
<BR> # SMTP - the address of =
the smtp=20
server to send the e-mail =
through<BR> =20
if o in ("-s",=20
"--smtp"):<BR>  =
; =20
smtpaddy =3D a</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial =
size=3D2> # Port -=20
port<BR> if o in ("-p",=20
"--port"):<BR>  =
; =20
port =3D a</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial =
size=3D2> # To -=20
the address to send the e-mail =
to<BR> =20
if o in ("-t",=20
"--to"):<BR> &=
nbsp;=20
towho =3D a</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial =
size=3D2> # From -=20
the reply address<BR> if o in =
("-f",=20
"--from"):<BR>  =
; =20
fromwho =3D=20
a<BR> =20
<BR> # Username - the username =
to=20
login as if required<BR> if o =
in=20
("-u",=20
"--user"):<BR>  =
; =20
user =3D =
a<BR> =20
<BR> # Password - the password =
of the=20
smtp server if required<BR> if =
o in=20
("-p",=20
"--pass"):<BR>  =
; =20
password =3D a</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial =
size=3D2> # Time -=20
amount of time in minutes to =
wait<BR> =20
if o in ("-w",=20
"--wait"): &nb=
sp;=20
<BR> =
wait =3D=20
int(a) * 60 </FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2> # Check for required =
and valid=20
command-line options<BR> if towho is=20
None:<BR> sys.stderr.write("To =
address=20
required.")<BR> =20
usage(2) =
<BR> if=20
fromwho is None:<BR> =20
sys.stderr.write("From address=20
required.")<BR> =20
usage(2) <BR> if wait <=20
300:<BR> =
sys.stderr.write("Invalid=20
wait value.")<BR> =20
usage(2)<BR> =20
<BR> <BR> =20
<BR> # Now we loop, checking the current address of =
the=20
machine against the address stored<BR> # in the =
file. If=20
we have a new address, we store that address in the file and=20
report<BR> # the new address by e-mail. We're =
depending=20
on Window's shutdown signal to stop<BR> #=20
properly<BR> while=20
(1):<BR> newaddy =3D=20
get_addy()<BR> if addy !=3D=20
newaddy:<BR> &=
nbsp;=20
print "New addy: ",=20
newaddy<BR> &n=
bsp; f=20
=3D open("ipwatch.dat",=20
"w")<BR>  =
;=20
f.write(newaddy)<BR>  =
; =20
f.close()<BR> =
=20
<BR> =20
try:<BR>  =
; =20
s =3D smtplib.connect(smtpaddy,=20
port)<BR> &nbs=
p; =20
if user is not=20
None: &n=
bsp; =20
<BR> &nb=
sp; =20
try:<BR>  =
; =
=20
s.login(user,=20
password)<BR> =
=20
except=20
SMTPAuthenticationError:<BR> &nb=
sp; &nbs=
p; =20
sys.stderr.write("Error logging into SMTP server. Check username =
and=20
password and=20
re-attempt")<BR> &nb=
sp; =20
s.sendmail(towho, fromwho,=20
newaddy)<BR> &=
nbsp; =20
s.quit()<BR> &=
nbsp; =20
</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial=20
size=3D2> &nbs=
p; except=20
SMTPException,=20
reason:<BR> &n=
bsp; =20
sys.stderr.write("SMTP Error: %s",=20
(reason))<BR> =
=20
addy =3D newaddy<BR> print =
"The current=20
address is", addy<BR> =20
time.sleep(wait) <BR>  =
; <BR> =20
</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2>if __name__ =3D=3D =
"__main__":<BR> =20
main()<BR> </FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Thanks</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Joel</FONT></DIV></BODY></HTML>
------=_NextPart_000_001E_01C228D9.50324040--