!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

ÆØÅ
Python
Børre Stenseth
Python >ting og tang

Ting og tang

Hva
Ting og tang som er greitt å vite i Python

endre path

Den typiske situasjonen er at vi ønsker å bruke en modul som ligger et sted som ikke er definert i den systemvariabelen som under Windows heter: PYTHONPAT. Måten å gjøre dette på er å endre pythonpath fra pythonkoden når vi trenger det. F.eks. kan det se slik ut:

import sys
sys.path+=['f:\\html\\cgi-bin\\mycat']
import mymodule

Du kan skrive ut stien til alle katalogene i sys.path slik:

for d in sys.path:
	print d

returnere en fil

I et CGI-script har vi ofte behov for å sende en ferdiglagd fil tilbake. Dette kan vi selvsagt gjøre ved å lese den inn i scriptet og skrive den tilbake på vanlig måte. Et alternative er følgende setning;

print "Location: http://www.it.hiof.no/~borres/ml/histo/p-histo.html\n"

En slik print kommer som alternativ til den vanlige

print "Content-type: text/html\n"
print .....

tegnkode

Håndtering av ulike tegnkoder kan skape trøbbel for oss på mange måter. Ett av problemener er å få skrevet kommentarer og/eller tekstkonstanter med æ,ø,å i en kilde fil. Vi kan fortelle Python-interpretatoren hva slags koding den kan forvente å finne med linja:

# -*- coding: latin_1 -*-

F.eks. slik:

#! /usr/bin/python2
# -*- coding: latin_1 -*-
# i dette scriptet vil jeg prøve å ....
import random,string,time,cgi

Dette gjelder fra Python versjon 2.3. Mer om ulike kodemuligheter finner du i Pythondokuamenstasjonen, 4.9.2 Standard Encodings.


norske elementnavn

Vi vet at vi kan ha XML-filer som ser slik ut:

<?xml version="1.0" encoding="utf-8"?>
<liste>
<person>
    <navn>Bøler</navn>
    <kjønn>m</kjønn>
</person>
...
</liste>

Tekst noder med norske tegn (Bøler) kan vi handtere i minidom ved å sørge for at vi skriver noe slikt når vi henter teksten:

if node.nodeType == node.TEXT_NODE:
            t=node.data.encode('ISO-8859-1')

og slik hvis vi ønsker å legge noe til en DOM-struktur kan vi lage unicode ved å skrive:

nyttnavn=unicode(originalnavn,'ISO-8859-1')

Dersom vi ønsker å søke i et register etter elementer med navn som har norske tegn kan vi bruke samme mekanisme. Vi gjør altså søkekriteriet om til unicode før vi bruker det:

sexkey=unicode('kjønn','ISO-8859-1')
resultat=person.getElementsByTagName(sexkey)

andre programmer

Av og til har vi behov for å kjøre andre programmer eller kommandoer fra et pythonskript. Et eksempel er når vi vil kjøre FOP fra et skript på serveren. (mer om FOP i modulen: XSL-FO )

Generelt kan vi kjøre en kommando slik:

	os.system("kommando")

der kommando er det vil ville ha kjørt fra kommandolinja. F.eks. skal vi kunne handtere en FOP-operasjon og ta vare på resultatet av operasjonen slik:

	os.system("/usr/local/fop/fop.sh myfile.fo myfile.pdf")
	file=open('myfile.pdf','r')
	resultat=file.read()
	file.close()

Dersom vi har en kommando eller et program som skriver til standard output, kan vi fange opp resultatet slik:

	f=os.popen("kommando")
	resultat=f.read()

ÆØÅ

Python dokumentasjon beskriver hvordan Python kan handtere ulike typer karakterer (character encoding). Normalt går det bra når vi leser og skriver tekstfiler med norske tegn. Når vi imidlertid bruker dom eller minidom får vi problemer med våre norske tegn dersom vi ikke passer på. Python bruker unicode i dom og vi må kode om dette før vi kan bruke teksten i andre sammenhenger, og før vi skriver til fil eller std out.

Min erfaring er at det går bra når jeg koder om (encode) strengene jeg plukker fra dom-treet. Følgende rutine som plukker ut alt tekstmateriale i et element ser ut til å gjøre jobben:

# collect all text in a node
def getText(nodelist):
    rc = ''
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            t=node.data.encode('ISO-8859-1')
            rc += t
    return rc

En kodesekvens som bruker rutina kan være slik:

   ...
   result=q.getElementsByTagName('headtxt')[0]
   T=getText(result.childNodes)
   ...

Likeledes kan vi plukke opp en attributt slik:

   ...
   T=en_node.getAttribute('att').encode('ISO-8859-1')
   ...

Vi kan bruke andre kodetyper enn ISO-8859-1, se Python dokumentasjonen. Begge eksemplene på stringkoding, tekstnoder og attributter, er brukt i eksemplene ovenfor.

laste ned en fil

Vi kan laste ned en fil fra nettet og lagre den som en lokal fil eller få tilgang til innholdet direkt.

import urllib
theUrl='http://www.ia.hiof.no/~borres/ml/python/frej1.txt'
theFile='c:\\tmp\\frej1.txt'
#Download a file and print it
try:
    f=urllib.urlopen(theUrl)
    S=f.read()
    f.close()
    print S
except:
    print 'cannot load'

#Download a file and save it locally
try:
    urllib.urlretrieve( theUrl,theFile) 
except:
    print 'cannot copy'

traversere en katalog

Vi kan løpe gjennom alle filer i en katalogstruktur på en enkel måte. Koden nedenfor gjør dette og skriver ut fullt filnavn for alle filer.

import os
   ...
def printAllFiles(catalog):
    for root, dirs, files in os.walk(catalog, topdown=False):
        for name in files:
            print os.path.join(root, name)

enumeration

Når vi lagrer data i lister blir ofte koden tunglest når vi aksesserer data ved index. Vi kan enkelt definere navn på de ulike indeksene.

(navn,year,city)=[0,1,2]
p1=['ole',1990,'Halden']
p2=['jens',1971,'Sarpsborg']
print p1[navn]
print p2[city]

,forutsatt at ikke listenes størrelse ordning og størrelse endres

exceptions

Vi kan skrive en generell exception handtering slik (Pythondoc 7.4 The try statement):

import sys
def test1(a,b):
    try:
        print a/b
    except:
        res=sys.exc_info()
        print res[1]

test1(None,None)
test1(2,1)
test1(2,0)

gir

unsupported operand type(s) for /: 'NoneType' and 'NoneType'
2
integer division or modulo by zero

printing utf-8

Det er mulig å endre egenskapene til std out

import codecs,sys
...
def setPrint():
    # Convert Unicode -> UTF-8
    (e,d,sr,sw) = codecs.lookup('utf-8')
    unicode_to_utf8 = sw(sys.stdout)
    sys.stdout = unicode_to_utf8

Skrape Wikipedia

Trolig går det bra med andre headere, kanskje med hva som helst untatt blank

import urllib2
import xml.dom.minidom
import sys
 

hdrs = { 'User-Agent': "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11" }
req=urllib2.Request('http://en.wikipedia.org/wiki/Snow_leopard',headers=hdrs)
fd=urllib2.urlopen(req)
text=fd.read()

Database

import MySQLdb
...
#-------------------------------------------------
# connect and execute a sql-request
# return a tuple. first is 'ok' or None
#-------------------------------------------------
def connectAndExecute(sql):
    #print sql
    try:
        myBase=MySQLdb.connect(host='frigg.hiof.no',
                               user='user',
                               passwd='hemmelig',
                               db='dbname')
        myTab=myBase.cursor()
        myTab.execute(sql)
        myBase.commit()
        myBase.close()
        return ('ok',myTab.fetchall())
    except MySQLdb.Error, e:
        return (None,"Error " + str(e))
Referanser
Vedlikehold
Børre Stenseth, sist modifisert september 2011
( Velkommen ) Python >ting og tang ( GoogleStuff )