Ting og tang
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))