[python-users] excel scripten vortrag

Detlef Lannert lannert at uni-duesseldorf.de
Mi Mär 4 19:27:53 CET 2009


Thomas Lenarz schrieb:
> Ich selbst nutze Excel sehr gerne (jetzt nicht lachen.... :-D) als
> Entwicklungswerkzeug im Zusammenhang mit SQL-Datenbanken:
 [...]
> Excel -> Datenbankinhalte: (brauche ich häufiger als die Gegenrichtung)
> -----------------------------------------------------------------------
>
> 1. Erzeuge leere Spalten zwischen den vorhandenen Datenfeldspalten und
> vor der ersten Spalte (ökonomisch mit "ganze Spalte markieren. STRG-+
> (im Nummernblock) )
>
> 2. Schreibe in die erste Spalte 'insert into tabelle values (
 [...]

Mit Python geht sowas viel bequemer ... Ich muß immer mal wieder aus einer
(von jemandem manuell gepflegten) Excel-Tabelle Konfigurationsdaten für
einen DHCP-Server generieren. Dazu nutze ich xlrd (aus dem Debian-Paket
python-xlrd; Homepage: http://www.lexicon.net/sjmachin/xlrd.htm). Es hat
sich als zuverlässiger erwiesen als die von mir ausprobierten Alternativen.

Die Daten schreibe ich anschließend im Textformat raus -- stattdessen
könnte man sie mit einem DBAPI-Datenbank-Adapter (oder einem ORM) auch in
eine relationale Datenbank schreiben. Als Anschauungsbeispiel hänge ich
unten eine geringfügig abgespeckte Fassung meines Skripts an, die auch
ohne viele Kommentare wohl selbsterklärend ist ...

Trotzdem zwei Hinweise dazu: Das Programm erwartet in der ersten Zeile der
ersten Tabelle Spaltenüberschriften; darunter müssen die wichtigen sein:
"IP", "Mac-Adresse" und "Benutzer". Danach kommen dann die Datenzeilen.

Beim Aufruf wird der Name der Excel-Datei erwartet, optional noch eine
Reihe von Mac-Adressen, die zu ignorieren sind.

Da ich nächste Woche nicht kommen kann, will ich so wenigstens einen
Beitrag zum xls-Thema leisten ... ;-)

Viele Grüße,
  Detlef

  --------------8<------------ snip --------------8<--------------
#! /usr/bin/python

# $Id: readdhcp.py,v ea7dc2e34bdb 2008/10/23 12:14:50 lannert $
# Author:  Detlef Lannert < lannert uni-duesseldorf de >
# Version: $Revision: ea7dc2e34bdb $

import xlrd
import sys

def read_xls(filename, sheet=None):
    book = xlrd.open_workbook(filename)
    for sheet_num, sheet_name in enumerate(book.sheet_names()):
        if sheet is None:
            sheet = sheet_name  # simply use the first sheet
        if sheet_name != sheet:
            continue
        sheet = book.sheet_by_index(sheet_num)
        return sheet

def read_addresses(d, filename, ignore=None):
    count = 0
    errcount = 0
    if ignore is None:
        ignore = []
    sheet = read_xls(filename)
    labels = sheet.row_values(0)
    try:
        ind_ip = labels.index("IP")
        ind_mac = labels.index("Mac-Adresse")
        ind_user = labels.index("Benutzer")
    except ValueError:
        raise ValueError("column headers not found in table")
    indmax = max((ind_ip, ind_mac, ind_user))
    row_num = 0
    while 1:
        row_num += 1
        try:
            row = sheet.row_values(row_num)
        except IndexError:
            break
        if len(row) < indmax + 1:
            sys.stderr.write("XXX short line: %s\n" % repr(row))
            errcount += 1
            continue
        ip = row[ind_ip]
        mac = row[ind_mac]
        user = row[ind_user]
        if not mac:
            continue
        ipnums = ip.split(".")  # some numbers have leading zeroes, some not
        if len(ipnums) != 4:
            raise ValueError("illegal IP address %s: %s" % (ip, repr(row)))
        ipnums = map(int, ipnums)
        ip = ".".join(map(str, ipnums))
        mac = mac.lower()
        mac = mac.replace(".", "")
        mac = mac.replace(":", "")
        mac = mac.replace("-", "")
        mac = ("%s%s:" * 5 + "%s%s") % tuple(mac)
        if not user:
            user = "pc_%s" % mac.replace(":", "")
        
        if mac in ignore:
            # e.g. the router address
            continue
        if mac in d:
            if d[mac][0] != ip:
                sys.stderr.write("duplicate MAC %s with IPs %s, %s\n" %
                        (mac, d[mac][0], ip))
                errcount += 1
            else:
                sys.stderr.write("duplicate entry %s %s\n" % (mac, ip))
            continue
        d[mac] = [ip, user]
        count += 1
    sys.stderr.write("%d entries used from %s\n" % (count, filename))
    if errcount:
        sys.stderr.write("%d errors\n" % errcount)

def main():
    if len(sys.argv) < 2:
        print "usage: %s <filename.xls> [<ignoremac> ...]" % sys.argv[0]
        sys.exit(1)
    filename = sys.argv[1]
    ignores = sys.argv[2:]
    
    arps = {}
    read_addresses(arps, filename, ignore=ignores)
    iplist = []
    for k in arps:
        iplist.append(map(int, arps[k][0].split(".")) + [k, arps[k][1]])
    iplist.sort()
    for entry in iplist:
        ipaddr = ".".join(map(str, entry[:4]))
        macaddr = entry[-2]
        user = entry[-1]
        name = "pc_%s" % macaddr.replace(":", "")
        print "host %s {\n\t# %s\n\thardware ethernet %s;\n\tfixed-address %s;\n}" %(
                name, user, macaddr, ipaddr)

if __name__ == "__main__":
    main()




Mehr Informationen über die Mailingliste python-users