Posts mit dem Label Python werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Python werden angezeigt. Alle Posts anzeigen

2022-11-07

Buch: Fluent Python: Clear, Concise, and Effective Programming

 Fluent Python, 2nd Edition

Ich habe die erste Auflage irgendwie verpasst und bin über einen Vortrag des Autors auf einer Python Conference auf das Buch gestoßen.

Keine leichte Kost und sicher nichts für Anfänger. Oder doch? Vielleicht is die breite der Informationen, bei der auch der langjährigen Python Benutzer (25+ Jahre in meinem Fall) noch viel mitnehmen kann. Auch die Verweise auf anderen Ressourcen am Ende jeden Kapitels sind wirklich eine Bereicherung. 

Achtung: Es gibt noch ein anderes Buch: "Fluent Python, Programming for Beginners". Dieses ist hier nicht gemeint,


2020-04-13

MoneyMoney von Python aus steuern

Ich benutze das hervorragende Programm MoneyMoney unter MacOS zum abfragen aller meiner Banktransaktionen. Mit war bekannt, dass es eine API in Lua gibt, mit denen man Erweiterungen schreiben kann. Unter anderem kann man eine Erweiterung laden, dass einem alle Amazon Einkäufe der letzten 23 Jahre .... aber lassen wir das.

Vor kurzem habe ich gelernt, dass man MoneyMoney auch via AppleScript fernsteure kann.

Also habe ich eine kleine Python Bibliothek zum testen gebaut. Näheres auf https://github.com/MirkoDziadzka/py-money 

2012-10-30

Vortrag: Praktische Anwendungen von Metaklassen

Heute habe ich auf der PyCon DE 2012 einen Vortrag zum Thema "Praktische Anwendungen von Metaklassen" gehalten. Die Folien und etwas Beispiel Code gibt es auf meiner Webseite.

2012-01-20

Vortrag: Fuse

Gestern habe ich einen kleine Vortrag zum Thema User Space Filesysteme mit Fuse gehalten.

2011-06-17

Vortrag: Python

Gestern habe ich zusammen mit Thijs auf dem monatlichen Treffen der OpenSolaris Usergroup München einen Vortrag zum Thema Python gehalten.

Hier sind die Folien für meinen Teil als PDF.

2011-03-10

Python parsing

Ich baue grade einen pure Python parser für OpenPGP Messages nach RFC 4880. Dabei ist mir wieder mal was aufgefallen.

Wenn man einen Parser baut, der eine grosse Datenstruktur analysiert und in Pakete zerlegt, hat man in den meisten Sprachen folgendes Muster:


In C würde man es wohl so machen:

void parse_message(char * input) {
    int len = find_packet_len(input);
    handle_packet(make_packet(input, len)); 
    input += len;
}

In Python ist der naive Ansatz:

def parse_message(input):
  while input:
     packet_len = find_length_of_packet(input)
     packet = input[:packet_len]
     handle_packet(input[:packet_len])
     input = input[packet_len:]

In funktionalen Sprachen entsprechend.

Das Problem ist nun, das Python an dieser  Stelle jeweils eine Kopie des Paketes und eine Kopie des restlichen Inputs anlegt. Letzteres ist leider eine O(n^2) Operation ....

Entweder baut man das parsing also um, indem man input als Array behandelt nur nur über Indizes adressiert:

def parse_message(input):
  start = 0
  while len(input) > start:
    pl = find_length_of_packet(input, start)
    handle_packet(input[start:start + pl])
    start += pl

Oder, man verfolgt weiter den Stil aus dem oberen Beispiel, legt aber einen Wrapper um den input, der das Kopieren verhindert:


class ROList(list):
    def __init__(self, l, start = 0):
        self.__l = tuple(l)
        self.__start = start
        self.__end = sys.maxint


    def __getitem__(self, i):
        return self.__l[self.__start + i]


    def __getslice__(self, start, end):
        #print self, start, end, sys.maxint - end
        res =  self.__class__("")
        res.__l = self.__l
        res.__start = self.__start + start
        if end < sys.maxint:
            res.__end = self.__start + end
        return res


    def __len__(self):
        if self.__end == sys.maxint:
            return len(self.__l) - self.__start
        else:
            return self.__end - self.__start


    def __repr__(self):
        return "%s : %d" % (self.__l, self.__start)

def test_performance(list_type):
    l = list_type(range(1024*1024))
    while l:
        l = l[512:]

if __name__ == "__main__":
    for t in list, ROList:
        start_time = time.time()
        test_performance(t)
        print 'test of %s performance: %f seconds' % (t, time.time() - start_time)

2009-10-29

Exceptions in Python sind langsamer als gedacht

Heute habe ich mal wieder ein Python Aha Erlebnis gehabt. Beim Optimieren einer Klasse habe ich ein paar Benchmarks zum Theme dict() Zugriff und Exception Handling durchgeführt.

Kurz gesagt, brauche ich eine Funktion, die ein Key in mehreren dicts sucht.


Klassisch in Python implementiert man das so:

def get_from_dict_list(dict_list,k):
    for d in dict_list:
        try:
            return d[k]
        except KeyError:
            pass
    return None
Eine alternative Implementation is

def get_from_dict_list(dict_list,k):
    for d in dict_list:
        if k in d:
            return d[k]
    return None
Die erste Methode wird normalweise bevorzugt. Dies hat zwei Gründe: Zum einen gilt der Spruch: "it's easier to ask forgiveness than permission" und exception handling ist ein integraler Bestandteil der Sprache. Zum anderen hat die zweite Methode potentielle Race-Conditions und kann eine unerwartete Exception werfen wenn k aus d gelöscht wird, während die Methode abgearbeitet wird.

Für den Fall, das der Key gleich im ersten dict gefunden wird, ist die erste Methode sogar leicht schneller. Falls aber das Exception Handling getirggert wird, wird es richtig langsam. Auf meinem Laptop liefert timeit einen Faktor von 10(!) zwischen den beiden Methoden, zugunsten der zweiten. Das Exception abfangen und ignorieren kostet auf meinem Laptop 4 Mikrosekunden

2005-12-14

Buch: Twisted Network Programming Essentials

Ein Buch über das Python Framework Twisted. Twisted basiert auf Asyncroner IO und Eventverarbeitung, dieses Modell ist für Netzwerserver sehr gut geeignet. Leider exisitierte für Twisted bisher keine Vernünftige Doku, dieses Buch ist der erste Versuch dazu. 

Fazit: Solides O'Reilly Werk mit viel Beispielcode. 

Lesenswert aufgrund der Konzepte, aber für die aktuelle Programmierung nehm ich dann doch lieber direkt asyncore aus der Standardbibliothek. 

Aber ich war schon immer für einfache Lösungen.