Nature

8 KB ought to be enough for anybody

, 2015-08-24T00:00:00+02:00

Bisher hatte ich mich nicht wirklich mit dem Speicher des Arduino beschäftigt. Am Wochenende wurde ich leider dazu gezwungen.

Als ich mit dem Programmieren anfing, war Arbeitsspeicher noch etwas, um das man sich kümmern musste. Mein erster Computer war ein Commodore VC-20, der hatte 5 KB RAM, wobei einem nur ca 3,5 KB zum Arbeiten zur Verfügung standen. Der Arduino MEGA2560, den ich im Klampfinator einsetze hat dagegen 256 KB. Das sollte also eine Weile reichen. Dachte ich zumindest bis gestern.

Der Soundcube

klampfibau.jpg

Da das Wetter angenehm war, und der Rest der Familie Termine hatte, war am Sonntag DIE Gelegenheit, einen größeren Umbau an der Software des Klampfinators vorzunehmen, den ich schon länger machen wollte. Bisher war es nämlich so, das ich hauptsächlich im Strumming - Modus gespielt habe. Da werden einfach alle Saiten angeschlagen (bis auf die gesperrten Saiten), und dann klingt das halt wie ein Akkord. Das Fingerpicking hatte ich bisher ebenso gelöst, es wurden immer gleiche Zupfmuster gespielt, während die linke Hand den Akkord vorgab. Leider ist das in der Realität beim Picking eben nicht so. Je nach gegriffenem Akkord, werden die gezupften Saiten ein wenig angepasst. Hauptsächlich im Bass-Bereich.

Dieses Verhalten muss der Klampfinator unbedingt auch beherrschen, denn einen falschen Ton hört man beim Picking sehr deutlich.

Zu diesem Zweck habe ich ein Konstrukt namens Soundcube eingeführt. Dabei handelt es sich aus Programmierersicht um ein 3-dimensionales Array aus Integern. So ein Array stellt man sich am besten als Würfel vor.

  • Die X-Achse stellt die 16 möglichen Akkorde dar, die mir an der linken Hand zur Verfügung stehen
  • Die Y-Achse stellt die 16 Picking-Patterns dar, die mit der rechten Hand wählbar sind
  • Die Z-Achse ist einer von 16 Momenten innerhalb eines Taktes

In jedem dieser Feldelemente liegt dann ein Integer, der angibt welche Saiten in diesem Moment wie laut gespielt werden müssen, und ob sie evtl. gleich wieder gemutet werden, etc. Dieser Würfel wird zum Liedbeginn einmal gefüllt, und danach nur noch gelesen. Der Speicherbedarf ergibt sich wie folgt:

Mem = 16 * 16 * 16 * 2 Byte (Integer) = 8192 Byte = 8 KB

Soweit, so gut. Kaum hatte ich die Programmierung realisiert und in den Arduino geladen, lief auch schon nichts mehr.

Ominöse Abstürze

Um den Fehler zu finden habe ich diverse Meldungen vom Programm zur Laufzeit ausgeben lassen. Das ist ja recht einfach möglich, weil der Klampfinator über ein kleines Text-Display verfügt. Das klappte auch ganz gut, solange ich den Soundcube im Code nicht initialisiert hatte. Sobald ich das aber tat, stürzte das Programm unkontrolliert ab. Manchmal hatte ich dann statt der erwarteten Variablenwerte im Display solche Ausgaben wie "wwwwwwww". Das war schon mal ein guter Hinweis darauf, das ich statt meiner erwarteten Anzeige hier offensichtlich ein beliebiges Stückchen Speicher sah.

Daraufhin habe ich mich mal kurz mit dem Speicher des Arduino beschäftigt, und siehe da schon auf den ersten Blick war klar, was hier gerade passiert. Der Arduino hat nämlich 3 verschiedene Speicher

  1. Flash-Speicher (256 KB): Hier wird der Programmcode abgelegt
  2. SRAM (8KB): Der Arbeitsspeicher des Arduino, in dem zur Laufzeit alle Variablen und der Stack abgelegt werden
  3. EEPROM (4KB): Ein Speicherbereich, den das Programm lesen und schreiben kann, und der auch nach dem abschalten des Arduino erhalten bleibt

Interessant ist für mich also der Bereich des SRAM, und den brauche ich schon alleine mit dem Soundcube komplett auf. Da bleibt weder Platz für auch nur eine einzige andere Variable, noch (und das ist für die Abstürze verantwortlich) für den Stack. Schöne Kacke!

Wege aus der Speicherkrise

Nun ist also Diät angesagt. Die Gesamtsumme aller Variablen des Programms darf zusammen 8192 Bytes nie überschreiten (eigentlich sogar noch weniger, da ja immer noch ein wenig Platz für den Stack bleiben muss, der ein paar Rücksprung-Adressen, und lokale Variablen enthält). In einem ersten Schritt bin ich zunächst mal meine Variablendeklarationen durchgegangen. Ich hatte zum Beispiel für jede mögliche Tonart einen Zähler hinterlegt, der eigentlich nur der Lesbarkeit des Codes für einen Menschen diente. Lesbarkeit kann man aber auch genauso gut in den Kommentaren erzeugen. Zack! 400 Bytes gespart. auf diese Weise ließen sich insgesamt gut 3 KB an Speicherbedarf einsparen.

Dann hat das Programm noch eine große Sammlung von eigentlich statischen Daten im Bauch. Das sind vor allem die möglichen Strumming- und Picking-Muster, sowie alle möglichen Akkorde, die sich greifen lassen. Da diese Werte sich nie ändern, sind diese ein heißer Kandidat für das EEPROM. Ich werde die Werte in der nächsten Version aus dem Programm herausnehmen, und davon ausgehen, das sie im EEPROM gelesen werden können. Dann muss ich nur noch ein kleines Programm schreiben, das die Daten einmalig dorthin befördert. Auf diese Art sollten sich noch einmal 3 KB einsparen lassen. Eventuell passt sogar noch die Menüstruktur ins EEPROM.

Als dritter Schritt wurde auch der Soundcube kleiner. An der Anzahl der Takte kann ich nicht schrauben, aber die Anzahl der Akkorde und der Picking-Muster lässt sich verringern. Für die Akkorde müssen es mindestens 8 sein, die Picking-Muster kommen theoretisch mit 2 aus, aber jedes Muster mehr macht das Spiel lebendiger. Wenn es sein muss kann ich also auf 8*2*16*2 Bytes herunter gehen, was einem halben KB entspricht. Ich werde es allerdings zunächst einmal mit 12 Akkorden und 12 Mustern versuchen, und komme damit auf einen Soundcube von 4,5 KB. Die restlichen 3,5 KB sollten für den Stack und die anderen Variablen reichen.

Insgesamt war die Fehlersuche ein amüsanter Ausflug zurück in die Anfänge des Programmierens, als Speicher noch wertvoll war. Ich bin gespannt welche der Tricks aus diesen alten Tagen ich bei der konkreten Lösung noch auspacken darf. Ich könnte z.B. einige der Daten auch binär noch etwas komprimieren.


Nature

Routine automatisieren mit udisks-glue

, 2015-06-09T00:00:00+02:00

Die Entscheidung Dropbox nicht mehr nutzen zu wollen, ist mir nicht leicht gefallen, denn dadurch war es wirklich kinderleicht Daten über verschiedene Geräte auf dem selben Stand zu halten. Gerade beim Abgleich von Kalender und Adressbuch mit dem Handy quasi ein No-Brainer.

Aber so zwang mich der Evolutionsdruck zu etwas, was ich schon immer mal machen wollte. Zum automatisieren von Routineaufgaben bei USB Geräten. Bei vielen Geräten tut man doch immer das gleiche. Wenn ich z.B. die Kamera anstöpsle, dann mache ich das eigentlich nur, um die Fotos, die sich darauf befinden auf den Rechner zu übertraagen. Das gleiche gilt für mein ZOOM Mikrofon. Beim Handy hole ich auch alle Bilder und Tonaufnahmen runter, und spiele den aktuellen Kalender, und das aktuelle Adressbuch auf.

Für solche Routineaufgabe bietet Linux ein tolles Tool an: "udisks-glue":http://manpages.ubuntu.com/manpages/precise/en/man1/udisks-glue.1.html. Dieses Tool überwacht die angeschlossenen Geräte, und bietet die Möglichkeit bei bestimmten Ereignissen eigene Scripts zu starten. Diese Ereignisse sind das ein- und ausstecken von Geräten, sowie das mounten, bzw unmounten.

Ich starte udisks-glue zusammen mit meinem Windows-Manager, damit er ständig aktiv ist:

bc. #!lua awful.util.spawnwithshell("udisks-glue")

Ab jetzt wartet udisks-glue auf Veränderungen im Geräte-Baum

Sobald eine Veränderung auftritt, wird diese zunächst mal duch eine Reihe von Filtern geschickt, um zu erkennen, welches Gerät da gerade eine Veränderung verursacht hat. bei mir sieht das so aus:

bc. #!css filter storagebird { uuid = "f8340488-c192-46e3-b91c-fa44081fa0db" } filter keydisk { uuid = "4e15ed71-1424-4a29-b04f-a48d2a6047e4" } filter kamera { label = "KAMERA" } filter kindle { uuid = "0000-000C" } filter handy1 { uuid = "287C-07CB" } filter handy2 { uuid = "40D7-7FFD" } filter mikrofon { uuid = "FC30-3DA9" }

Wie man sieht erkenne ich die meisten Geräte anhand ihrer uuid. Lediglich die Kamera erkenne ich am Label der eingelegten SD-Karte, damit ich die auch mal einfach direkt in den Kartenleser an meinem Laptop stecken kann, wenn mal wieder der Akku an der Kamera leer ist.

Die Begriffe wie storagebird oder kamera sind frei wählbar, und geben dem gefundenen Gerät einen sprechenden Namen. Außerdem werden sie in den nun folgenden Match-Regeln verwendet

bc. #!css match keydisk { automount = false automountoptions = sync postinsertioncommand = "pmount %devicefile keydisk" postmountcommand = "notify-send %mountpoint" } match kamera { automount = false automountoptions = sync postinsertioncommand = "pmount %devicefile kamera" postmountcommand = "/home/andy/bin/kamerasync.sh" }

Das Automounten gewöhne ich den USB-Geräten damit grundsätzlich ab, und ersetze es im postinsertioncommand, also nach dem einstöpseln durch das pmount Kommando, welches das Gerät einhängt, es mir aber auch als normaler User erlaubt, das Gerät später wieder mittels pumount auszuhängen. Nach dem einhängen, wird dann ausgeführt, was ich im postmountcommand eingetragen habe, und da nutze ich nur die beiden oben angezeigten Varianten.

  1. Anzeigen des Einhängepunktes mittels notify-send, oder
  2. Ausführen eines Scripts

Das Script erledigt dann schlußendlich die eigentlichen Routine-Aufgaben. Für meine Kamera sieht das beispielsweise so aus:

bc. #!bash #! /bin/bash espeak "Kamera found" espeak "Please wait for synchronisation" espeak "Moving pictures" mv /media/kamera/DCIM/MSDCF/*.* ~ cd ~ espeak "Sorting pictures" renrot –aggr-mode template -e JPG espeak "Thank you"

Die vielen espeaks sorgen lediglich dafür, dass ich über den Fortschritt der Arbeiten informiert werde, in diesem Fall per Sprachausgabe. Zunächst werden also alle Bilder aus dem entsprechenden Verzeichnis in mein Home-Verzeichniss verschoben. Die Kamera ist damit wieder leer, und bereit für neue Aufnahmen. Danachlasse ich renrot (rename & rotate) auf diese Dateien los. Dadurch wir mir ein Image-Ordner angelegt, der die Aufnahmen tageweise in Ordner einsortiert. Damit sind sie in der Regel schon mal in auch thematisch zusammenhängenden Ordnern. Diesen Ordnern gebe ich dann später noch Namen wie Geburtstagsfeier oder Ausflug-Maker-Faire und schiebe sie dann in mein Archiv


Nature

Emacs vs. Vim - die Lösung

, 2015-03-31T00:00:00+02:00

Wer, wie ich, am liebsten mit reinen Text-Dateien arbeitet, wird eines Tages vor der Frage stehen: "Mit welchem Text-Editor mache ich das denn am besten?" Wenn man dann in Nerd-Kreisen fragt bekommt man in der Regel eine von zwei Antworten. 'Vim' oder 'Emacs'. Und damit kennt man auch schon die beiden Teilnehmer der Editor-Wars des Glaubenskrieges zwischen den Anhängern zweier Texteditoren, der etwa so lange dauert, wie der "Knäckebrotkrieg von Hovdala":https://familynomadic.wordpress.com/tag/double-wars/ bei dem die Teilnehmer seit mehr als einem Vierteljahrhundert um die Frage kämpfen, ob das Knäckebrot auf der glatten oder der gelochten Seite gebuttert werden muß.

h3. Vim

!>GVim-screenshot.png(Screenshot of gVim editor displaing HTML source code)!

Beiden gemeinsam ist, das sie von Hause aus eine eher spartanische Oberfläche mitbringen, und für einen Benutzer, der normalerweise mit einem Office-Paket arbeitet zunächst einmal unbedienbar sind. Jeder auf seine eigene Weise. Da aber beide Editoren ihre treue Fangemeinde haben, habe ich vor über einem Jahr beschlossen, mir mal Vim näher anzusehen. Die gängigste Witz über Vim ist ja, das nur deshalb so viele Menschen ihn benutzen, weil noch niemand herausgefunden hat, wie man ihn wieder beendet. Und in der Tat, die Tastaturbelegung ist schon gewöhnungsbedürtig, wenn man Vim gestartet hat und einfach lostippt wird man zum beispiel feststellen, das sich am Bildschirm absolut nichts tut, bevor man nicht zufällig das i wie insert gedrückt hat.

Von dieser Art hat Vim noch eine Menge zu bieten. die meisten Tastaturkürzel ergeben einen Sinn, wenn man sich die Funktionsnamen über das englische herleitet, und so war ich nach ca einem Vierteljahr in der Lage Vim als meinen alleinigen Editor zu benutzen. Mit ein paar Erweiterungen (und die sind es, die sowohl Vim als auch Emacs so mächtig machen) fand ich Vim sogar besser als jeden anderen Editor, mit dem ich vorher gearbeitet hatte. Insgesamt ein Jahr habe ich ausschließlich mit Vim gearbeitet. Sehr angenehm war auch, das man nur eine Konsole braucht um mit Vim zu arbeiten, und ich daher auf dem Server einfach in der gewohnten umgebung bleiben konnte.

h3. Emacs

!<emacs.png(A screenshot of Emacs showing several Dired buffers)!

Beim ersten Treffen des "Warpzonista Coding Clubs":http://remline.de/2015/WarpzonistaCodersClub/ habe ich dann im Gespräch erwähnt, das ich versuche, so viel wie möglich mit Ascii-Dateien zu arbeiten, und erhielt dort den Tipp: 'Dann ist der Emacs "Org-Mode":http://orgmode.org/" wahrscheinlich was für dich'. Und in der Tat, ich hatte bereits früher schon wesentlich mehr lobende Erwähnung für den Org-Mode (eine möglicher Betriebmodus des Emacs) gehört, als über Emacs selbst. Dieser Hinweis war für mich der konkrete Anlass, es mal mit Emacs zu versuchen. Und tatsächlich, auch Emacs wartet mit eine ganzen Reihe sehr kruder Tastenkombinationen auf, die sich hier allerdings nicht so klar über das englische herleiten lassen, und dazu noch in verschiedenen Betriebsmodi unterschiedliche Funktionen haben können. Nicht umsonst spielt der gängigste Emacs Witz damit, dass der Name eigentlich eine Abkürzung für Esc-Meta-Alt-Ctrl-Shift sei. Eine dieser Tasten ist gefühlt ständig gedrückt.

Von der Tastenbelegung her ist Emacs also wirklich grausam, allerdings ist das Konzept wie Tastendrücke auf Editorfunktionen abgebildet werden deutlich lockerer gekoppelt, und so fällt es bei Emacs leichter mal eben einer Funktion eine andere Tastenkombination zuzuweisen. !ABER HALT! ich hatte schon vor Etwa einem Jahr mit Vim festgestellt, das man sich dabei schnell selbst in den Fuß schießen kann, weil man am Ende mit eine System dasteht, das mit keiner Dokumentation mehr übereinstimmt, und bei dem einem das nächste Zusatzmodul die Belegung zerschieß. Außerdem hat dann der Editor auf dem Server wieder eine "normale" Tastenbelegung, und man ist aufgeschmissen.

h3. Die Lösung

Diesen Gedanken habe ich ein paar Tage in meinem Kopf hin und her gerollt. Der Org-Mode unter Emacs ist wirklich toll, und entspricht genau meinem arbeiten. Ich denke in Baumstrukturen, und kann das dort 1:1 abbilden. Andererseits wird mir eine starke Anpassung der Tasten das arbeiten an fremden Emacs' verleiden. Ich stand also erstmals vor der Frage "Vim oder Emcs - Wie gehts weiter?" Und wie so oft liegt die Lösung darin, sich dem entweder/oder Ansatz zu verweigern. Ich kann immerhin Vim recht fließend bedienen, und werde die Grundzüge dessen wohl auch so schnell nicht verlernen, also kann ich überall dort, wo ich Remote arbeiten muß ja durchaus bei Vim bleiben, auf die Tastatur meines Laptops legt sowieso niemand die Finger außer mir, also kann ich mir dort meinen Emacs auch einfach so einrichten, das ihn außer mir niemand bedienen kann. Ich werde mir jede Funktion exakt dorthin legen, wo mein erstes Gefühl sie erwartet.

Die Antwort lautet also Vim und Emacs Es ist ein wenig wie das einrichten eines Wohnzimmers, in dem man sich die nächsten 10 Jahre wohl fühlen möchte. Emacs scheint mir dafür eine gute Grundlage zu bieten. Immerhin arbeite ich an einem PC und da darf ich das "personal" in "Personal Computer" durchaus mal wörtlich nehmen.

Wie ist das bei euch? Achtet ihr drauf, das ihr auf euren PC genauso arbeiten könnt, wie bei Freunden, oder bei der Arbeit? Wodurch wir euer PC zu eurem persönlichen Gerät?


Nature

abtool, das Adressbuch Werkzeug

, 2015-03-26T00:00:00+01:00

abook.jpg

Wer dieses Blog schon länger verfolgt, hat mit Sicherheit mitbekommen, das ich Programme mag, die Ihre Daten in einfachen Ascii-Dateien ablegen. Eines dieser Programme ist die Adressverwaltung abook. Die Datei die abook anlegt ist aufgebaut, wie man es von früheren Windows Konfigurationsdateien gewohnt ist. Ein Eintag sieht beispielsweise so aus:

[168]
name=Restaurant Royals & Rice
custom2=51.964056, 7.6215647
address=Frauenstraße 51-52
city=Münster
state=NRW
zip=48143
country=Deutschland
workphone=+4925139633699
url=http://royalsandrice.com
notes=Mo-Sa 09:00-24:00, So 10:00-24:00

Ich nenne diese Art der Datenverwaltung gerne LoTek, nach den Rebellen aus der Kurzgeschichte Der mnemonische Johnny von William Gibson. Sie macht mich völlig unabhängig von der Software, mit der ich die Daten bearbeite, ich kann sie mit den simpelsten Programmen lesen und verarbeiten. Kein Softwarehaus kann mich in seine Software binden, nur weil ich bei einem Wechsel alle Daten noch mal neu erfassen müsste.

We are LoTek. Fracking the system, it's what we do. Reject the accepted paradigm. See you on the road…

So beschreibt es einer der LoTek Anhänger in der Geschichte.

Von Hause aus kann abook bereits eine Mail an eine Adresse schreiben, bzw eine Webseite anhand der gespeicherten URL aufrufen. Leider muß ich dazu immer noch das Programm öffnen, den entsprechenden Eintrag suchen, und dort die entsprechenden Tasten drücken. Außerdem fehlten mir noch ein paar Funktionen.

Die erste davon, die ich mit einem eigenen kleinen Python-Skript umgesetzt habe, ist der Aufruf einer Karte, die mir anzeigt, wo sich eine Adresse befindet. Der gewünschte Aufruf sollte so aussehen

@abmap royals@ 

und dann sollte im Browser OpenStreetMap geöffnet werden, und das Restaurant aus dem Beispiel in der Karte markiert sein.

Das Skript

Generell ist das Skript, so simpel wie es bisher auch ist, bereits in zwei Teile unterteilt.

  1. Einer Klasse, die die Schnittstelle zur abook Adressdatei darstellt, und
  2. einem kurzen Programm, welches diese Klasse nutzt.

Fangen wir mit dem Nutzteil an. Dieser ist recht übersichtlich:

# Only execute this if we are called directly
if __name__ == "__main__":

# parse arguments

    parser = argparse.ArgumentParser(description='Searches for entries in an abook address-file and takes some actions on it.',
				     epilog='If you find there are some useful actions missing, feel free to report them.')

    parser.add_argument('name', nargs='+')
    parser.add_argument('-n','--nick', nargs = '*', metavar = 'Fieldname')

    if sys.argv[0].split('/')[-1] != 'abmap':
	parser.add_argument('-m','--map', action = 'store_true')
    if sys.argv[0].split('/')[-1] != 'abmail':
	parser.add_argument('-e','--email', action = 'store_true')
    if sys.argv[0].split('/')[-1] != 'aburl':
	parser.add_argument('-u','--url', action = 'store_true')

    parser.add_argument('-v','--verbose', action = 'count') # FATAL, ERROR, WARN, INFO, DEBUG 
    parser.add_argument('-q','--quiet', action = 'store_true')
    parser.add_argument('-V','--version', action='version', version='%(prog)s 0.1')

    args = parser.parse_args()


    book = Abook()

    name = " ".join(args.name)
    coordinates = book.coordinates(name)
    for x, y in coordinates:
	webbrowser.open_new("https://www.openstreetmap.org/?mlat=" + x + "&mlon=" + y +"#map=16/" + x + "/" +y )

Der gesamte erste Teil, mit den vielen @parser.gedöns@ Zeilen dient dazu die Kammandozeile des Programms auszuwerten. Im Moment kann man dort nur einen Namen, oder Teile eines Namens eingeben, aber das Programm soll in Zukunft noch ausgebaut werden, und dazu habe ich schon mal eine Handvoll Aufrufparameter vorgesehen. Interessant wird es erst in den letzten 5 Programmzeilen.

Hier wird zunächst book als Instanz des Adressbuchs angelegt. Danach werden die Suchbegriffe der Kommandozeile in die Variable name verfrachtet. Zu diesem name lassen wir uns nun eine Liste von Koordinaten zurückgeben. Für jede einzelne der Koordinaten wird nun eine Webseite geöffnet, die die entsprechenden Koordinaten in Openstreetmap anzeigt, und markiert.

coordinates ist dabei eine Liste von (x,y) Tupeln. Eine Liste daher, weil wir unter umständen mit unserem Suchbegriff mehrere Treffer erhalten, und ein Treffer unter Umständen auch mehrere Adressen enthalten kann.

Die Klasse

Schauen wir uns die Funktion @coordinates(name)@ einmal genauer an:

def coordinates(self, searchname):
    pattern = "(-?[1234567890]+\.[1234567890]+)[^-.1234567890]+(-?[1234567890]+\.[1234567890]+)"
    coords = re.compile(pattern)
    result = []

    for name in self.searchname(searchname):
	for entry, value in name:
	    match = coords.search(value)
	    if match != None:
	       result.append((match.group(1),match.group(2)))

    return result

Die ersten beiden Zeilen bereiten das Suchmuster - hier als regulären Ausdruck - vor. Zu beachten sind dabei vor alem die beiden Paare von Runden Klammern, die jeweils eine Gruppierung innerhalb des Suchausdrucks darstellen. Danach wird über die searchname Funktion eine Liste von Treffern zu unserem Suchbegriff zurückgeliefert, über die wir iterieren. Jeder Treffer enthält eine Liste von Tupeln aus Keyword und Wert, wie sie in der Textdatei von oben standen. Wenn in diesen Werten nun irgendwo ein Match auf eine Koordinate stattfindet, wird der Resultate liste ein Tupel aus den beiden Gruppen dieses Matches hinzugefügt. Jede Gruppe enthält einen Teil der Koordinate.

Die Suche nach einem Treffer zu unserem Suchbegriff habe ich ausgelagert, da wohl verschiedene Funktionen in Zukunft nach einem Namen suchen können möchten. Die Funktion selbst sieht so aus:

def searchname(self, searchname):

    result=[]

    for s in self.abook.sections():
	if self.abook.has_option(s,'name'):
	    name=self.abook.get(s,'name')
	    if name.lower().count(searchname.lower()) > 0:
		result.append(self.abook.items(s))

    return result

Dabei ist @self.abook@ die klasseninterne Variable, mit der auf die Datei zugegriffen wird. Genau genommen allerdings nicht auf die Datei als @file@ Object, sondern wir benutzen hier, da es sich ja um eine Datei handelt, die sich wie eine Windows-Config Datei verhält, die Python Klasse @ConfigParser@. Die einzelnen Personen darin sind als @sections@ bezeichnet, die Attribute jeder Person als @options@. Im Detail ist das hier dokumentiert.

Entsprechend einfach gestaltet sich also auch die Init-Funktion der Klasse:

def __init__(self):
    "Takes an abook file an reads it"

    self.abook = ConfigParser.ConfigParser()
    self.abook.read(os.environ["HOME"] + "/.abook/addressbook")
    self.abook.remove_section('format')

Wie man sieht greife ich hier auf eine hard-coded Adressbuch-Datei zu. Ja ja, extrem schlechter Stil! Aber um das in zukünftigen Versionen nicht tun zu müssen haben wir ja die Kommandozeilen-Parameter vorbereitet. Das komplette Python-Skript findet sich auf Github als derzeit erstes im LoTek Repository. Die anderen Skripte werde ich hier ebenfalls hinzufügen.


Nature

Trinkgewohnheiten

, 2015-03-20T00:00:00+01:00

Die "Bildungstrinker":http://bildungstrinken.com/ haben einen Fragebogen in die Runde geworfen, und da mich solche Stöckchen an die gute alte Blogging Zeiten erinnern, und ich das Thema auch ganz interessant finde, habe ich mich einfach schamlos bedient. Gefunden habe ich das übrigens in "Anne Schüßlers Blog":http://anneschuessler.com/2015/03/20/trinkgewohnheiten/

1. Was ist dein liebster Drink?

Wenn ich die freie Auswahl habe Whisky. Am liebsten Talisker. Falls es nur Long Drinks gibt dann auch mal ein Mai Tai. In 2/3 aller Fälle trinke ich aber eher alkoholfreies.

2. Wann hast du das erste mal Alkohol getrunken?

Da war ich wohl ein echter Spätzünder, denn das war mit 24 bei meinem ersten Diskothekenbesuch. Ich war auf einer Zivi-Schulung, und es war abends total langweilig dort. Was es genau war, weiss ich nicht mehr, aber vermutlich Bier. Zum ersten Mal betrunken war ich mit 28, bei einem Dubliners-Konzert vom Guinness.

3. Welchen Drink hast du am meisten bereut?

Im Sinne von "Es war die Folgen nicht wert" habe ich mich mal im Rahmen einer Weihnachtsfeier in einer Mittelalterkneipe durch die Met-Karte getrunken. Leider mit ansteigender Süße, am Ende war mir glaube ich mehr von der Süße schlecht, als vom Alkohol. Ist aber immerhin alles dringeblieben.

Falls es um den Geschmack geht war das ganz klar "Braken". Das ist der lokale Schnaps, der hier im Ort ausgeschenkt wird. Auf Wermutbasis. Wi-der-lich. Aber da ich nun mal hier wohne, wollte ich den örtlichen Schnaps wenigstens mal probiert haben. Ich glaube der tiefere Sinn, dieses Gebräu herzustellen besteht in einer Art Aufnahmeritual, bei dem geprüft wird, wie ernst es der Kandidat damit meint, in die Dorfgemeinschaft aufgenommen zu werden. Ich empfange auch jeden mit offenen Armen, der das Zeug einfach an die Wand spuckt.

4. Bar oder Kneipe?

Alles, wo ein nettes Zweier-Gespräch möglich ist, und es nicht nach abgestandenem Bier riecht.

5. Champagner oder Schaumwein?

Ich habe bisher nur einmal kurz an einem Champagner genippt, daher kann ich das nicht wirklich beurteilen. Andererseits mag ich eine Sorte Sekt wirklich gern, fast alle anderen aber überhaupt nicht.

6. Mit wem würdest du gerne trinken?

Ich nehme mal an hier sind Leute gemeint, die irgendwie prominent sind. Carolin Kebekus fällt mir da ein, oder Bernhard Hoëcker. Gregor Gysi, und ich hätte da noch ein paar Fragen an Joschka Fischer. Außerdem unbedingt mit Nora Tschirner und dem Dalai Lama.

7. Bei wem würdest du gerne trinken?

Ich würde mich gerne mal durch meine Twitter-Timeline trinken. Am liebsten hätte ich zwei Wochen Zeit, und würde jeden Abend jemand anderen daraus besuchen, und dann einfach mittrinken, was dort Usus ist. Von Tee bis Vodka…

8. Wie sieht deine Hausbar aus und was ist das Kostbarste darin?

Die "Hausbar" besteht aus einer Ecke der Vitrine, in der sich derzeit exakt 3 Flaschen befinden:

Ich trinke etwa 1-2 Flaschen Whiskey pro Jahr. Den Tullamore bekomme ich immer zu Weihnachten von den Schwiegereltern, und den Talisker kaufe ich nach, wenn der leer ist. ansonsten haben wir außer dem Wein meiner Frau in der Regel keinen Alkohol im Haus. Bier erreicht bei uns immer das Ablaufdatum.

9. Beschreib deine Eiswürfel.

Da haben wir hier ein altes Familienrezept, bei dem ich nicht weiß, ob ich das verraten darf. Nur so viel, es besteht aus nur einer Zutat, und viel Kälte. Das Ergebnis ist ein recht kalter Quader und hat in meinem Whisky (bzw. Whiskey beim Tullamore) nix zu suchen.

10. Was ist deine Gin-&-Tonic-Empfehlung?

Ich habe bisher weder Gin noch Tonic getrunken, daher empfehle ich mir einfach mal einen auszugeben, wenn ihr mich mal irgendwo trefft. Damit würdet ihr euren Bildungsauftrag erfüllen.

11. Wie bekämpfst du deinen Hangover?

Ich versuche ihn zu vermeiden, und das ist mir bisher auch ganz gut gelungen. Die Anlässe zu denen ich einen Hangover befürchten musste kann ich immer noch an einer Hand abzählen. Daher trinke ich keinen harten und weichen Alkohol durcheinander an einem Abend, und versuche fuseliges zu vermeiden. Ich versuche dann dem Körper noch vor dem Schlafen möglichst was gutes zu tun. Ein Freund, der in einem Krankenhaus arbeitete empfahl immer einen Tropfbeutel "Ringer-Laktat-Lösung":http://flexikon.doccheck.com/de/Ringer-Laktat-L%C3%B6sung aus einem Glas zu trinken (Zitat:" Aber eiskalt, sonst bekomms'te das Zeug nicht durch'n Hals") weil da alles drin sei um die Körperchemie möglichst schnell wieder auf einen brauchbaren Level zu bringen. Da ich sowas nicht im Hause habe improvisiere ich normalerweise mit 2 großen Tomaten, mit soviel Salz, wie gerade noch schmackhaft ist. Dann hat der Körper während des Schlafs schonmal Zeit, das im Körper zu verteilen.


Andy Drop

I like it, when I see the intentions of a code author, and i like to see it written down in remark lines. Why didn't someone do that with the world. It would be far easier to understand. So I started to document my world wherever I see the need to do so. In text. With Emacs Org mode. I want to share this world with you.


Categories

  • Emacs logoEmacs
    The OS-like text editor
  • Org mode logoOrg mode
    Emacs built-in mode for organizing everything
  • Plaintext logoPlaintext
    Using plain text for everything