Python
Sisukord
- 1 Sissejuhatus
- 2 Pythoni paigaldamine
- 3 Programmeerimine Pythonis
- 4 Pythoni interpretaator
- 5 Pythoni skript
- 6 Sõne-operatsioonid
- 7 Andmestruktuurid
- 8 Failioperatsioonid
- 9 Tingimused
- 10 Kordused
- 11 Funktsioonid
- 12 Moodulid
- 13 HTTP
- 14 try-except-else lause
- 15 Unicode
- 16 PostgreSQL andmebaasi kasutamine
- 17 MySQL andmebaasi kasutamine
- 18 SMTP
- 19 DNS
- 20 LDAP
- 21 Help kasutamine
- 22 Programmide käivitamine shellist
- 23 UDP sõnumi saatmine
- 24 Alamprotsesside loomine
- 25 Lõime kasutamine
- 26 Käsurea argumentide kasutamine skriptis
- 27 Standard-sisendi kasutamine skriptis
- 28 Regulaaravaliste kasutamine
- 29 OOP
- 30 Märkused
- 31 Kasulikud lisamaterjalid
Sissejuhatus
Python (ingl. k. püüton) http://www.python.org/ on suhteliselt populaarne programmeerimiskeel, mille lõi Guido van Rossum http://en.wikipedia.org/wiki/Guido_van_Rossum 1980 aastate lõpus ja millele peetakse iseloomulikuks
- kasutamise lihtsus, st kiiresti õpitav ja saab kiiresti jõuda kasutatavate tulemusteni
- keele küpsus
- sobib mitmekesiste ülesannete lahendamiseks (ingl. k. general purpose language)
- sunnib kasutajat kirjutama nö loetavat programmi
- Python on skriptimiskeel (ingl. k. scripted language) st programmid on koheselt käivitatavad ja ei vaja kompileerimist
- Python sisaldab objektorienteeritud programmeerimise (OOP) võimalusi, kuid neid ei pea tingimata kasutama (käesoleva teksti punkt Python#OOP on pühendatud sellele)
- Python on vaba tarkvara
2010 aastal on levinud kasutada kahte erinevat Python keele põlvkonda, sõltuvalt kasutusalast või kasutamise asjaoludest võib see olla oluline, kumba konkreetsel juhul eelistada
- 2.x - juba pikka aega kasutuses olnud versioon, mida jätkuvalt toetatakse
- 3.x - uuem versioon, millega reeglina vana versiooni jaoks kirjutatud programmid ei tööta; nt print direktiiv ja teksti vs binari failide käsitluse osa on oluliselt muutunud
Mõned populaarsed vaba tarkvaralised Pythoni rakendused on näiteks
- Mailman - postiloendi serveri (ingl. k. listserver) tarkvara
- Trac - veebipõhine veahalduse ja versioonikontrolli tarkavara
- Zope, Plone - veebikeskkonnad
Pythonis valmistatud tarkvara on loetletud aadressil http://en.wikipedia.org/wiki/List_of_Python_software.
Järgnev tekst sisaldab kahte osa
- keele vahendite tutvustus - tegu ei ole ammendava käsitlusega, kuid piisavaga selleks, et asuda Pythonit kasutama ning et tekiks ettekujutus Pythoni võimalustest
- nö kokaraamatu (ingl. k. cookbook) osa - keskendutud on süsteemiadministreerimisel vajalikele kasutusjuhtumitele, nt meili saatmine, http, ldap ja dns päringute esitamine, kodeeringutega tegelemine jms kasutades seejuures Pythoni teekide võimalusi.
Esitatud tekst kehtib v. 2.x kohta kui teksti sees ei ole versiooni täpsustatud.
Pythoni paigaldamine
Debian Lenny paketihalduses on olemas kaks Pythoni versiooni
- 2.5.2 - vaikimisi
- 2.4.6 - võimalik lisaks paigaldada
Python v. 2.5.2 paigaldmiseks sobib öelda (tegelik paketinimi on python2.5)
# apt-get install python
Programmeerimine Pythonis
Üldiselt võib väita, et programm 'teeb midagi millegagi', konkreetsemalt sobib kujutleda Pythoni kasutamist sellise hierarhiana
- programmid koosnevad moodulitest
- moodulid koosnevad lausetest (ingl. k. statement)
- laused koosnevad avaldistest (ingl. k. expression)
- avaldised tekitavad ja töötlevad objekte
Python on
- dünaamilise tüübiskeemiga (ingl. k. dynamically typed) keel - programmi käivitamisel ajal (ingl. k. runtime) toimub tüüpide üle otsustamine; st praktiliselt, et nt muutujate väärtustamisel ei pea nende tüüpe kirjeldama
- tugeva tüübiskeemiga (ingl. k. strongly typed) keel - erinevat tüüpi muutujatega ei saa teha teatud operatsioone, nt liita arv ja sõne
Pythoni interpretaator
Pythoni interpretaatori kasutamine interaktiivses režiimis toimub selliselt
$ python Python 2.5.2 (r252:60911, Jan 24 2010, 14:53:14) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> a="tervist" >>> print a tervist >>> Ctrl+D $
Interpretaator sobib nt kalkulaatorina kasutamiseks
>>> 21.0/8 2.625
Pythoni skript
Pythoni skript esineb tekstifaili kujul, kusjuures sisu kirjutamisel tuleb jälgida, et tulemust mõjutab ka ridade alguses kasutatud tühikute hulk, st taane (ingl. k. intendation). Nt selline skript kirjutab välja arvud ühest kolmeni
for i in range(3):
print i + 1
kus
- range(3) funktsioon tekitab loendi elementidega 0, 1, 2 ja 3
- for-kordus tegeleb järjekorras kõigi elementidega
- print esitab i + 1 avaldise väärtuse iga for korduse jaoks, kusjuures print on trepitud (ingl. k. to intendate)
Skripti käivitamiseks sobib öelda
$ python skript.py 1 2 3
Alternatiiviks on lisada faili algusse rida interpretaatori nimega
#!/usr/bin/python for i in range(3): print i+1
ning muuta fail käivitatavaks
$ chmod 0755 skript.py
ning käivitada
$ ./skript.py
Lisaks töötavatele ridadele võib skriptis esineda kommentaare, kõike # märgist paremale jäävat käsitletakse kommentaarina.
Sõne-operatsioonid
Sõnedega (ingl. k. string) saab teha nt selliseid operatsioone
- omistada muutujale ja esitada
linn = "Tartu" print linn
- liita
linn = "Tartu" print "Asukoht " + linn
- küsida elementi, vastatakse 'r'
sone = "Tartu" print sone[2]
Andmestruktuurid
Pythonis kasutatavad enamlevinud nn sisse-ehitatud (ingl. k. built-in) andmestruktuurid on
- sõne - järgnevus tähti-numbreid-muid-sümboleid
- arv - nt täisarv või ujukomaarv
- loend (ingl. k. list) - ...
- korteež (ingl. k. tuple) - järjestatud hulk, mille elemente ei saa muuta
- sõnastik (ingl. k. dictionary) - mõnedes keeltes tuntud ka kui assotsiatiivne massiiv (ingl. k. associative array, ka hash)
Sõne
Sõne (ingl. k. string) on järgnevus tähti-numbreid-muid-sümboleid
'abcdefgh'
Arv
Arv (ingl. k. number) võib olla nt täisarv või ujukomaarv
15
Kuna Python on tugeva tüübiskeemiga keel, siis nt ei saa liita arve ja sõnesid, eelnevalt tüleb tüüp teisendada, nt
print 'mina tulen kell ' + str(10)
Loend
Loend (ingl. k. list) on järjestatud hulk
loend = ['yks', 'kaks', 'kolm']
Loendi elemendi poole pöördumine toimub selliselt
print loend[1]
Loendiga saab sooritada mitmeid iseloomulikke tegevusi, nt
- järjekorra ümberpööramine
print loend.reverse()
- elemendi lisamine
loend.append('neli')
- elemendi jrk numbri küsimine
loend.index('kaks')
- loendi saab täita loendi genereerimise (ingl. k. list comprehension) teel võttes aluseks olemasoleva loendi
loend = [ 10, 20, 30 ] comp = [ 3*x for x in loend ] for i in comp: print i
või sisu arvutusest genereerida
comp = [ 2*x for x in range(10) ] for i in comp: print i
Korteež
Korteež (ingl. k. tuple) on järjestatud hulk, mis erineb loendist nt selle poolest, et selle on oluliselt vähem funktsionaalsust, mis põhiliselt tuleneb asjaolust, et korteeži elemente ei saa muuta
k = ('yks', 'kaks', 'kolm')
Korteeži saab kasutada for-korduse juures ning tema elemente saab järjekorra alusel küsida, nt
print k[2]
Loendi teisedab korteežiks funktsioon tuple()
k = tuple(loend)
Sõnastik
Sõnastik (ingl. k. dictionary) on key-value paaridest koosnev järjestamata hulk
sonastik = { 'priit': 167, 'mart': 196 }
Sõnastiku elemendi väärtuse esitamine toimub nii
print sonastik['priit']
Hulk
Hulk (ingl. k. set) on järjestamata kogum elemente
hulk1 = set(['essa', 'tessa', 'kossa', 'nessa'])
Hulkadega saab teha nt selliseid tehteid
- ühend (summa)
print hulk1 | hulk2
- ühisosa (lõige, korrutis)
print hulk1 & hulk3
Nagu alguses kasutatud, loendi teisendamiseks hulgaks sobib kasutada set funktsiooni
hulk = set(loend)
Ning hulga teisendamine loendiks (kusjuures tulemuse järjestusele ei maksa toetuda) toimub funktsiooniga list
loend = list(hulk)
Failioperatsioonid
Failioperatsioonid tegelevad failist lugemise ja faili kirjutamisega.
Lugemine
Tekstifailist lugemiseks sobib kasutada nt sellist järgnevust
for rida in open ('urlid.txt'):
print rida.rstrip()
kus
- open ('urlid.txt') - avab tekstifaili
- rstrip() eemaldab rea lõpust reavahetuse märgi
- lugemine toimub for-korduse abil rida haaval
Kirjutamine
Tekstifaili kirjutamiseks sobib kasutada nt sellist järgnevust
read=('loomaaed.tartu.ee', 'kuutorvaja.eenet.ee', 'www.eesti.ee')
myfile = open ('urlid','w')
for rida in read:
myfile.write (rida + '\n')
myfile.close()
kus
- myfile = open ('urlid','w') - tekstifail urlid avatakse lugemiseks ja kirjutamiseks
- read - on korteeži element, mis on loendi moodi konstruktsioon, kuid mille sisu ei saa peale moodustamist muuta
- kirjutamine toimub for-korduse abil rida haaval
Tingimused
Pythonis saab kasutada selliseid tingimusi
- if-elif-else tingimus
x = 1
if x < 0:
print 'Alla nulli'
elif x == 0:
print 'Null'
elif x == 1:
print 'Yks'
else:
print 'Suurem yhest'
Kordused
Pythonis saab kasutada selliseid kordusi
- for-kordus
loend = ['Priit', 'Mart', 'Laa']
for i in loend:
print "Tervist " + i
- while-kordus
i = 0
while i < 5:
i = i + 1
print i
Kordusest saab tulla välja break abil, nt
l = [ 'essa', 'tessa', 'kossa', 'nessa' ]
for i in l:
if i == 'kossa':
print "if seest print", i
break
print "if jarel print", i
print "for jarel print", i
annab sellise väljundi
$ python skript.py if jarel print essa if jarel print tessa if seest print kossa for jarel print kossa
Funktsioonid
Funktsioonid võimaldavad üldiselt kahte asja
- korraldada programmi osade korduvkasutust
- jagada programmi loogilisteks osadeks
Funktsioon kireldatakse def direktiivi abil, nt selliselt
def korrutamine(x, y):
return x * y
print korrutamine(15, 3)
kus
- esimesed kaks rida kirjeldavad funktsiooni
- return tagastab funktsiooni väljakutsele väärtuse
- viimases reas toimub funktsiooni väljakutse
Pythoni funktsioonide kohta öeldaks, et nad on polümorfsed, st nad töötavad suvaliste sisendaandmetega eeldusel, et funktsioonis kirjeldatud operatsioone saab sooritada nende andmetega. Nt sobiks ülaltoodud funktsiooni välja kutsuda selliselt
print korrutamine ('mina ', 3)
Funktsiooni dokumentatsioon
Pythoni funktsiooni saab dokumenteerida esitades vahetult def järel kolmekordsete jutumärkide vahel teksti
def korrutamine(x, y): """Korrutaja Korrutab """ return x * y
Sellist dokumentatsiooni saab lugeda nt selliselt
print korrutamine.__doc__
Moodulid
Moodulite abil organiseeritakse programmi teksti kõige üldisemal tasemel. Nt esitatud moodul vastab failile aritmeetika.py ning seal on kirjeldatud üks muutuja ning kaks funktsiooni
$ cat aritmeetika.py
pii = 3.14
def liida(x, y):
return x + y
def lahuta(x, y):
return x - y
Seda moodulit kasutab nt selline skript
import aritmeetika
print "Pii väärtus on ", aritmeetika.pii
print aritmeetika.liida(2, 3)
Mooduli poole pöördumiseks kasutatakse järgnevust 'mooduli-failnimi.moodulis-kirjeldatud-objekt', nagu näitest on näha võib see objekt olla muutuja või funktsioon.
Tehniliselt on kõik Pythoni skriptid moodulid.
Parasjagu kasutada oleva süsteemi moodulirada näeb öeldes
>>> import sys >>> print sys.path [' ', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', \ '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', \ '/usr/lib/python2.5/site-packages', '/usr/lib/pymodules/python2.5']
kus listi esimene element on tegelikult 'kaks ülakoma järjest', mis tähistab käesolevat kataloogi. Importimisel otsib Python otsib moodulid järjest nendest kataloogidest, otsinguteele saab lisada katalooge keskkonnamuutuja PYTHONPATH abil, nt
$ export PYTHONPATH=/opt/python-libs
Moodulis kirjeldatud objektide nimekirja küsimiseks sobib öelda
>>> import moodulinimi >>> dir(moodulinimi) ['__builtins__', '__doc__', '__file__', '__name__', 'korrutaja', 'pii']
Nimeruum
Peale programmi sisse mooduli importimist saab tema objektide poole pöörduda kujul
moodulinimi.objektnimi
Öeldakse, et programmi jaoks on tekkinud mooduli nime ja seal kirjeldatud objektide nimedele vastav nimeruum (ingl. k. namespace).
Paketid
Lisaks failidele saab mooduleid paigutada spetsiaalselt moodulite hoidmiseks moodustatud kataloogidesse. Sellist kataloogi nimetatakse paketiks (ingl. k. package) ja seal peab sisalduma fail __init__.py. Paketi kujul esitatud moodulite laadimiseks tuleb programmis öelda
import katalooginimi
Seejuures täidetakse esmalt __init__.py faili sisu, see fail võib olla ka tühi, ning seejärel kõik kataloogis olevad moodulitele vastavad failid.
Paketi kataloogistruktuur võib olla ka mitmetasemeline, üldiselt toimub moodulis kirjeldatud objektide kasutamine selliselt
katalooginimi1.katalooginimi2.funktsiooninimi()
Mooduli kasutuskoha kontroll
Üldiselt võib olla vaja moodulit nii kasutada importimise teel kui ka otseselt käivitades. Selleks, et neid kahte juhtumit eristada, sobib kasutada mooduli sees ühte if-tingimust ja muutuja nime, mis on erinev sõltuvalt kasutusjuhust. Nt selliselt
pii = 3.14
def liida(x, y):
return x + y
def lahuta(x, y):
return x - y
if __name__ == '__main__':
print "mind käivitatakse otse"
kus
- __name__ muutuja väärtus on otse käivitamisel '__main___' ning importimisel vastava faili nimi
Baitkood
Skripti poolt kasutatavate moodulite jaoks moodustatakse skripti esmakordsel käivitamisel esmalt baitkood (ingl. k. bytecode) ja see baitkood käivitatakse Pythoni virtuaalsel masinal. Baitkood tekitatakse automaatselt samasse kataloogi mooduliga samanimelise failina, mille nime lõpus on .pyc.
Järngevatel skript käivitamistel kontrollitakse moodulite ja moodulitele vastavate baitkoodi failide viimase muutmise aegu ning selle järgi otsustatakse, kas baitkood tuleb uuesti moodustada. Kui baitkoodi pole vaja moodustada, siis Python kasutab olemasolevat baitkoodi ning skripti käivitamine toimub baitkoodi moodustamisele kuluva aja võrra kiiremini.
Võiks ette kujutada, et baitkood on midagi lähtekoodi ja masinkoodi vahepealset, nt tema kasutamise efektiivsuse mõttes.
HTTP
HTTP päringute tegemiseks on Pythonis kaks teeki
- urllib - kõrgema abstraktsusega teek, mida soovitatakse reeglina kasutajal kasutada, http://docs.python.org/library/urllib.html
- urllib2 - täiendava funktsionaalsusega teek, nt basic auth
- httplib - madalama taseme teek, mida kasutab omakorda ka urllib, http://docs.python.org/library/httplib.html
Skript http päringu vastuse päise elemendi esitamiseks
import httplib
conn = httplib.HTTPConnection("www.python.org")
conn.request("GET", "/index.html")
r1 = conn.getresponse()
print r1.getheader('last-modified')
Lihtsa HTTP serveri, mis serveerib üle HTTP käesoleva kataloogi sisu, saab käivitada selliselt
$ python -m SimpleHTTPServer 8080 Serving HTTP on 0.0.0.0 port 8080 ...
Basic auth
import urllib2
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='Tekst millega veebikoht nö tervitab',
uri='https://svn.loomaaed.tartu.ee/projektid/',
user='priit',
passwd='parool')
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
f = urllib2.urlopen('https://svn.loomaaed.tartu.ee/projektid/projektinimi/trunk/sql/LoeMind.txt')
print f.read(100000)
try-except-else lause
Python võimaldab programmi töös esineda võivaid erindeid (ingl. k. exception) st praktiliselt veasituatsioone püüda try-except lause abil.
Skript
- kirjeldab loendi URLID
- käib läbi loendis URLID toodud hostide /index.html ressursid
- kui ressursi poole ei õnnestu pöörduda püütakse see try/except poolt kinni
import httplib
URLID = ('www.python.org',
'kuutorvaja.eenet.ee',
'seda.pole')
for i in URLID:
try:
conn = httplib.HTTPConnection(i)
conn.request("GET", "/index.html")
except:
print "ei saa avada http://" + i + "/index.html"
else:
r1 = conn.getresponse()
print i + " " + r1.getheader('content-length')
Käivitamisel esitatakse nt selline väljund
$ python for.py www.python.org 16961 kuutorvaja.eenet.ee 267 ei saa avada http://seda.pole/index.html
Unicode
Pythonis saab töötada Unicode'iga sh UTF-8 kodeeringus tekstiga, http://docs.python.org/howto/unicode.html.
Skript UTF-8 formaadis faili kirjutamiseks (sisuks on Ä ja à tähed)
file = open('utf8data.txt', 'w', encoding='utf-8')
size = file.write('\xc4\xc3\n')
file.close ()
PostgreSQL andmebaasi kasutamine
Psycopg http://initd.org/psycopg/ võimaldab Pythonist kasutada PostgreSQL andmebaasi. Tarkvara paigaldamiseks Debian operatsioonisüsteemis sobib öelda
# apt-get install python-psycopg2
Andmete lugemine
Skript küsib andmebaasi tabelist priit.priidutabel kahte väärtust
import psycopg2
conn = psycopg2.connect("dbname=baasinimi host=192.168.1.247 user=kasutajanimi password=kasutajaparool port=portnumber")
cur = conn.cursor()
cur.execute("SELECT nimi, vanus FROM priit.priidutabel where nimi = 'Priit Kask';")
read = cur.fetchall()
for rida in read:
print ('Nimi: %s, vanus: %s' % rida)
cur.close()
conn.close()
kus
- connect() parameeter on ühendussõne
- cur.fetchall() tagastab vastused korteežidena
Andmete sisestamine
Andmete baasi sisestamisel tuleb lisaks öelda commit
import psycopg2
conn = psycopg2.connect("dbname=baasinimi host=192.168.1.247 user=kasutajanimi password=kasutajaparool port=portnumber")
cur = conn.cursor()
cur.execute("insert into priit.priidutabel (vanus, nimi) values ('28', 'Mart Kask');")
cur.close()
conn.commit()
conn.close()
Binary andmete sisestamine
Binary andmeid hoitakse bytea tüüpi väljas, nt sellises tabelis
CREATE TABLE bitea.tabelinimi(name TEXT, ablob BYTEA);
Andmeid saab sisestada sellise skriptiga
import psycopg2, cPickle
connection = psycopg2.connect()
cursor = connection.cursor()
data = cPickle.dumps('binaarne sisu', 2)
sql = "INSERT INTO bitea.tabelinimi VALUES(%s, %s)"
cursor.execute(sql, ('esimesevaljavaartus', psycopg2.Binary(data)))
connection.commit()
cursor.close()
connection.close()
MySQL andmebaasi kasutamine
MySQL-Python http://mysql-python.sourceforge.net/ võimaldab Pythonist kasutada MySQL andmebaasi. Tarkvara paigaldamiseks Debian operatsioonisüsteemi sobib öelda
# apt-get install python-mysqldb
Andmete lugemine
Skript küsib andmebaasi tabelist priit.priidutabel kahte väärtust
import MySQLdb
conn = MySQLdb.connect(db="baasinimi" host="192.168.1.247" user="kasutajanimi" passwd="kasutajaparool" port=portnumber)
cur = conn.cursor()
cur.execute("SELECT nimi, vanus FROM priit.priidutabel where nimi = 'Priit Kask';")
read = cur.fetchall()
for rida in read:
print ('Nimi: %s, vanus: %s' % rida)
cur.close()
conn.close()
kus
- connect() parameeter on ühendussõne
- cur.fetchall() tagastab vastused korteežidena
Andmete sisestamine
Andmete baasi sisestamisel tuleb lisaks öelda commit
import MySQLdb
conn = MySQLdb.connect(db="baasinimi" host="192.168.1.247" user="kasutajanimi" passwd="kasutajaparool" port=portnumber)
cur = conn.cursor()
cur.execute("insert into priit.priidutabel (vanus, nimi) values ('28', 'Mart Kask');")
cur.close()
conn.commit()
conn.close()
SMTP
TODO
Plaintext
Skript saadab smtp serveri kaudu välja kirja
import smtplib
fromaddr = "From: Priit Kask <priit@loomaaed.tartu.ee>"
toaddrs = "To: Mart Kask <mart@loomaaed.tartu.ee>"
msg = fromaddr + "\n" + toaddrs + "\nSubject: test" + "\nkirja sisu"
server = smtplib.SMTP('192.168.1.250')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
MIME multipart
nn MIME multipart kirja saatmist käsitleb nt viimane näide aadressilt http://docs.python.org/library/email-examples.html
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
me = "priit@loomaaed.tartu.ee"
you = "mart@loomaaed.tartu.ee"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you
# Create the body of the message (a plain-text and an HTML version).
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"
html = """\
<html>
...
HTML tekst
"""
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
# Send the message via local SMTP server.
s = smtplib.SMTP('smtp.loomaaed.tartu.ee')
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
s.sendmail(me, you, msg.as_string())
s.quit()
DNS
Pythoni seest DNS kasutamiseks sobib kasutada dnspython http://www.dnspython.org/ tarkvara, paigaldamiseks Debian keskkonnas tuleb öelda
# apt-get install python-dnspython
Selline skript esitab tekstifailis toodud domeeninimedele vastavate A kirjete ip aadressid
import dns.resolver
for rida in open ('hostid'):
try:
answers = dns.resolver.query(rida.rstrip(), 'A')
for rdata in answers:
print rida.rstrip() + " " + str(rdata)
except dns.resolver.NXDOMAIN:
print ('Domeeninimel %s puudub A kirje' % rida.rstrip())
LDAP
Pythoni seest LDAP kataloogi kasutamiseks sobib tarkvara python-ldap http://www.python-ldap.org/, paigaldamiseks Debian keskkonnas tuleb öelda
# apt-get install python-ldap
Skript LDAP kataloogist päringu tegemiseks, küsitakse kõik andmed
import ldap
l = ldap.initialize('ldap://192.168.1.247')
result_set = l.search_s('dc=loomaaed,dc=tartu,dc=ee',ldap.SCOPE_SUBTREE,'(objectClass=*)',['cn', 'uid', 'loginShell'])
for i in result_set:
print i
Tulemuseks olev result_set on loend korteežidest, viimane for-kordus esitab nende korteežide väärtused, üks real.
Help kasutamine
>>> help() Welcome to Python 2.5! This is the online help utility. If this is your first time using Python, you should definitely check out the tutorial on the Internet at http://www.python.org/doc/tut/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and return to the interpreter, just type "quit". To get a list of available modules, keywords, or topics, type "modules", "keywords", or "topics". Each module also comes with a one-line summary of what it does; to list the modules whose summaries contain a given word such as "spam", type "modules spam". help>
Sisestades help> prompti järele huvipakkuva mooduli nime saab selle mooduli kohta teavet, nt
help> smtplib Help on module smtplib: NAME smtplib - SMTP/ESMTP client class. FILE /usr/lib/python2.5/smtplib.py MODULE DOCS http://www.python.org/doc/current/lib/module-smtplib.html DESCRIPTION This should follow RFC 821 (SMTP), RFC 1869 (ESMTP), RFC 2554 (SMTP Authentication) and RFC 2487 (Secure SMTP over TLS). ...
Programmide käivitamine shellist
Aadressil http://jimmyg.org/blog/2009/working-with-python-subprocess.html on toodud mitmeid näiteid subprocess mooduli kasutamise kohta
import subprocess
pipe = subprocess.Popen(["df", "-h"], stdout=subprocess.PIPE)
print pipe.communicate()[0]
Väljastatakse kahe elemendilise korteeži esimene element.
UDP sõnumi saatmine
Aadressil 192.168.10.35:514/udp töötavale syslogile sõnumi saatmiseks sobib selline järgnevus
import socket
port = 514
host = "192.168.10.35"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto("test sonum\n", (host, port))
Alamprotsesside loomine
Alamprotsesside loomise (ingl. k. to fork) teel saab käivitada paralleelselt mitmeid protsesse. Alamprotsessi loomisel moodustatakse olemasolevast protsessist koopia, ning edasi töötab arvutis kaks protsessi
- vanem (ingl .k. parent) - protsessi, milles toimus fork funktsiooni väljakutse
- laps (ingl. k. child) - fork tulemusena tekkinud uus protsessi
Põhimõtteliselt töötab alamprotsessi moodustamine selliselt, tulemusena on käivitatud töötavast programmist juurde teine eksemplar
import os
def child( ):
print 'Siin laps', os.getpid( )
os._exit(0) # else goes back to parent loop
def parent( ):
while 1:
newpid = os.fork( )
if newpid == 0:
child( )
else:
print 'Siin vanem ', os.getpid( ), newpid
if raw_input( ) == 'q': break
parent( )
kus
- def parent ( ) - kirjeldab funktsiooni, mis programmi täitmisel esmalt käivitatakse
- def child ( ) - kirjeldab funktsiooni, mille täitmine kutsutakse parent funktsioonist välja
- parent funktsioonis toimub os.fork() funktsiooni väljakutse, mille tulemusena arvuti mälus on kaks samasisulist programmi, millest üks on vanem ja teine laps; nende edasi töötamisel laps puhul on rahuldatud tingimus 'if netpid == 0' ning muul juhul on tegu vanemaga
- programmi töö lõpetab while kordusest q sisestuse abil väljumine
Forkimise järel aga ei pea laps olema tingimata sama sisuga kui vanem, näiteks alltoodud skript kasutab os.execlp funktsiooni asendades lapse programmi funktsiooni argumendiks olevate väärtustele vastava tegevusega kopeerides ftp serverist faile
import os
filesetid = ('bsd', 'base46.tgz', 'comp46.tgz', 'etc46.tgz', 'man46.tgz', 'misc46.tgz')
for fileset in filesetid:
pid = os.fork()
if pid == 0:
os.execlp('wget', 'wget', '-q', 'http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/' + fileset)
assert False, 'error starting program'
else:
print 'fileset: ', pid
raw_input( )
Skripti töötamise ajal paistavad protsessitabelis sellised sissekanded
# ps auf USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND priit 31463 0.0 0.2 19040 2076 pts/2 S<s 06:30 0:00 -bash priit 32009 0.1 0.4 16420 3068 pts/2 S<+ 08:03 0:00 \_ python fork-dl.py priit 32010 0.0 0.2 26372 2036 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/bsd priit 32011 0.2 0.2 26372 2032 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/base46.tgz priit 32012 0.1 0.2 26372 2036 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/comp46.tgz priit 32013 0.1 0.2 26372 2028 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/etc46.tgz priit 32014 0.0 0.2 26372 2032 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/man46.tgz priit 32015 0.0 0.2 26372 2032 pts/2 S<+ 08:03 0:00 \_ wget -q http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/misc46.tgz
Lõime kasutamine
Lõimed võimaldavad sarnaselt alamprotsesside moodustamisele korraldada paralleelselt tegevusi, kuid selle erinevusega, et kõik tegevused toimuvad ühe ja sama protsessi sees. Võrreldes protsessidega on lõimedele iseloomulik, et kõik lõimed jagavad omavahel mitmeid ressursse, nt globaalseid muutujaid ja seega erinevate lõimede vahel võib olla mõnel juhtumil lihtsam korraldada andmevahetust kui erinevate protsesside vahel.
Lõime (ingl. k. thread) kasutamine toimub põhimõtteliselt selliselt
import thread
def child(tid):
print 'Tervist loimest nr', tid
def parent( ):
i = 0
while 1:
i = i+1
thread.start_new(child, (i,))
if raw_input( ) == 'q': break
parent( )
kus
- skript käivitab funktsiooni parent ( )
- parent ( ) seest kutsutakse välja while korduse sees thread.start_new() abil lõimena funktsioon child()
- thread.start_new() täitmise lõppu ootamata liigutakse skriptis edasi
Järgnev skript kopeerib ftp serverist faile
import thread
import urllib
def child(fileset):
print 'Tervist loimest, kopeerin faili: ', fileset
urllib.urlretrieve('http://ftp.aso.ee/pub/OpenBSD/4.6/amd64/' + fileset, fileset)
filesetid = ('bsd', 'base46.tgz', 'comp46.tgz', 'etc46.tgz', 'man46.tgz', 'misc46.tgz')
for fileset in filesetid:
thread.start_new(child, (fileset,))
raw_input( )
kus
- raw_input( ) - kui klaviatuurilt sisestust mitte oodata, siis jõuaks programmi täitmine lõpule enne kui lõimed on lõpetanud
Tulemusena töötab kokku protsessis seitse lõime
$ ps -aeLf | grep python | grep -v grep UID PID PPID LWP C NLWP STIME TTY TIME CMD priit 1308 880 1308 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1309 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1310 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1311 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1312 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1313 0 7 15:06 pts/0 00:00:00 python loim-ftp.py priit 1308 880 1314 0 7 15:06 pts/0 00:00:00 python loim-ftp.py
kust on näha, et kõigil ridadel on sama PID väärtus kuid erinevad LWP väärtused.
Käsurea argumentide kasutamine skriptis
sys.argv loend sisaldab programminime ja käsureal kasutatud argumentide väärtusi, skript
import sys
for i in sys.argv:
print i
väljastab käivitamisel
$ python skript.py yks kaks kolm skript.py yks kaks kolm
Standard-sisendi kasutamine skriptis
Selleks, et skript kasutaks standard-sisendi (ingl. k. stdio) sobib kasutada nt sellist konstruktsiooni
import sys
next = sys.stdin.readline
while 1:
rida = next()
if not rida:
break
print rida.rstrip()
Kasutamiseks sobib öelda
$ cat tekstifailinimi | python skript.py
Regulaaravaliste kasutamine
Skript esitab tekstifailist tunnusele vastavad read
import re
for rida in open ('tekstifail.txt'):
matchobj = re.search('muster', rida)
if matchobj:
print rida.rstrip()
Tühikute pealt loendi moodustamine
>>> p = re.compile(r'\s+') >>> p.split('all tcp 192.168.2.47:1433 <- 10.0.5.13:2746 ESTABLISHED:ESTABLISHED') ['all', 'tcp', '192.168.2.47:1433', '<-', '10.0.5.13:2746', 'ESTABLISHED:ESTABLISHED']
OOP
Objekt-orienteeritud programmeerimine (OOP) tähendab vähemalt kahte asja
- mõtteviisi, mida kasutatakse ülesandega tegelemiseks
- konkreetseid keele poolt pakutavaid OOP vahendeid
class nimed:
def __init__(self, domeeninimi, omanik ):
self.domeeninimi = domeeninimi
self.omanik = omanik
self.ttl = 86400
def suurendattl(self, kordaja):
self.ttl = self.ttl * kordaja
# objektid moodustamine
eesti = nimed(domeeninimi = 'eesti.ee', omanik = 'Calevipoeg')
tartu = nimed(domeeninimi = 'tartu.ee', omanik = 'Dor Batt')
# too objektidega
eesti.suurendattl(2)
# tulemuste esitamine
print eesti.omanik
print (eesti.ttl)
kus
- class nimed - kirjeldab klassi 'nimed'
- def _init__ - nn konstruktor, mis on tehniliselt tavaline funktsioon kusjuures ta täidetakse klassi põhjal instance'i moodustamisel esimesena; tavaliselt kirjeldatakse seal muutujate vaikeväärtused
- def suurendattl - tööd tegev meetod
- eesti = nimed(...) - klassidest instance'ite moodustamine
Märkused
- Skriptist väljumine etteantud exit code'iga, nt Nagiose agentide puhul vajalik
>>> import sys >>> sys.exit(2) $ echo $? 2
Kasulikud lisamaterjalid
- http://www.python.org/, http://docs.python.org/
- Learning Python, 4rd editon (v. 2.6 ja 3.0), Mark Lutz
- Programming Python, 3rd Mark Lutz
- Python Cookbook, 2rd edition, Alex Martelli, Anna Martelli Ravenscroft, David Ascher
- http://en.wikipedia.org/wiki/Python_(programming_language)
- Ruby