»Swift 5« ist erschienen

Die neueste Auflage meines umfassenden Handbuchs zu Swift ist erschienen. In dem Buch berücksichtige ich auf über 1300 Seiten natürlich alle wichtigen Neuerungen von Swift 5. Ein neues Kapitel behandelt auf vielfachen Leserwunsch Core Data und SQLite. Stark überarbeitet habe ich den Abschnitt zur Lokalisierung von Apps. (Xcode zickt dabei wie eh und je …) Außerdem gibt es da und dort ein paar neue Beispiele (Slider-Puzzle-App, macOS Dark Mode etc.) Weitere Details zum Buch finden Sie hier.

Wie üblich kann das Buch beim Rheinwerk Verlag oder bei Amazon vorbestellt werden. Die E-Book-Ausgabe bzw. das Bundle aus Buch und E+Book gibt es allerdings nur beim Rheinwerk Verlag!

Ubuntu 19.04

Ubuntu 19.04 ist ein Release ohne dramatische Neuerungen. Optisch springen neue Icons in Auge, die dem Desktop mehr Frische geben. Gnome 3.32 unterstützt fractional scaling, was die Arbeit auf hochauflösenden Displays verbessern sollte. Das Feature gilt aber noch als experimentell und muss explizit aktiviert werden. Generell verspricht Gnome etwas mehr Performance. Die lässt sich in Benchmarktests messen, gefühlt hat sich aber nicht viel geändert.

Der Desktop wirkt mit neuen Icons und einem originellem Hintergrundbild gleich ein wenig frischer

Update 25.4.2019: Installation auf einem Lenovo P1 durchgeführt. Keine Probleme (Details siehe unten).

Update 26.4.2019: Desktop-Icons deaktivieren (siehe unten)

Ubuntu 19.04 weiterlesen

Postfix, Dovecot + SpamAssassin: Spam in den Junk-Folder verschieben

Auf vielen Mail-Servern läuft SpamAssassin, um Spam-verdächtige Mails mit einer Header-Zeile zu markieren. Ordentliche Mail-Client wie Thunderbird können dann mit einer simplen Filter-Regel derartige Mails aussortieren.

Noch besser wäre es aber, wenn die Mails bereits auf dem Server in einen eigenen Junk-Folder verschoben würden. Das ist insbesondere dann praktisch, wenn zum Lesen von Mails auch diverse Mail-Clients auf Smartphones, iPads etc. verwendet werden, die keine Filtermöglichkeiten bieten.

Postfix, Dovecot + SpamAssassin: Spam in den Junk-Folder verschieben weiterlesen

Modulverwaltung in Thonny

Thonny ist eine praktische kleine Python-Entwicklungsumgebung, die ideal für Python-Einsteiger geeignet ist. Allerdings verwendet das Programm eine eigene Python-Installation, die von einer eventuell vorhandenen systemweiten Python-Installation vollkommen losgelöst ist. Das gilt auch für die installierten Module. Wenn Thonny also die Fehlermeldung module not found liefert, dann müssen Sie das Modul innerhalb von Thonny installieren.

Modulverwaltung in Thonny weiterlesen

Pop!_OS

Die Linux-Distribution Pop!_OS ist von Ubuntu abgeleitet und wird von der amerikanischen Firma system76 entwickelt. Diese Firma verkauft Notebooks, auf denen standardmäßig Pop!_OS installiert ist. Im Vergleich zu anderen Distributionen ist Pop!_OS besonders gut für Notebooks mit NVIDIA-Grafik optimiert.

Ursprünglich dachte ich, Pop!_OS sei nur ein weiterer Ubuntu-Klon mit modifiziertem Gnome-Desktop und integrierten NVIDIA-Treibern. Seit ich die Distribution auf mein neues Lenovo-P1-Notebook installiert habe, weiß ich, dass Pop!_OS weit mehr Eigenheiten hat.

Nach dem Gusto des Autors modifizierter Gnome-Desktop von Pop!_OS

Pop!_OS weiterlesen

Auf der Suche nach einem Linux-Notebook

Mein aktuelles Notebook ist ein Lenovo E320 (2012, i3-CPU, notebookcheck). Erstaunlicherweise funktioniert das Gerät noch immer passabel, aber naturgemäß geht es dem Ende seiner Tage entgegen. In den letzten Tagen habe ich mich näher dem Notebook-Markt auseinandergesetzt. Das Ziel ist ein leistungsstarkes Notebook, das nicht nur unterwegs eingesetzt werden soll, sondern täglich als Desktop-Ersatz. Bei meiner Suche bin direkt in die NVIDIA-Falle gestolpert …

PS: Dieser Blog-Beitrag hat zugegebenermaßen den Charakter eines persönlichen Notizzettels. Klar ist auch, dass die folgende Übersicht nur eine Momentaufnahme (Februar 2019) sein kann; ich habe nicht vor, den Text in Zukunft zu aktualisieren. Aber vielleicht helfen die gesammelten Informationen und die vielen Links anderen Leuten, die gerade auf der Suche nach einem Traum-Linux-Notebook sind :-)

Update 10.3.2019: Ich habe mich für ein Lenovo P1 entschieden. Gründe: Tastatur, Verarbeitungsqualität, zwei NVMe-Slots. Hier ist ein Erfahrungsbericht.

Update 2.5.2019: Dell bietet ab sofort das Notebook Precision 3540 mit AMD-Grafik und Ubuntu an. Ein interessantes Angebot.

Update 27.9.2019: Nochmals Dell, jetzt mit einem NVIDIA-freien XPS-15-Modell: Test bei notebookcheck

Auf der Suche nach einem Linux-Notebook weiterlesen

Neu in Swift 5

Am 26. März wurde Swift 5 fertiggestellt. Dieser Beitrag fasst die wichtigsten Neuerungen zusammen. Swift 5 gilt insofern als »Meilenstein«, als Apple erstmalig die binäre Kompatibilität der Schnittstellen garantiert. Die größte Auswirkung in der Praxis besteht darin, dass Standardbibliotheken nun auf Apple-Geräten installiert werden und nicht mehr mit jeder App mitgeliefert werden müssen. Xcode erzeugt daher kleinere Binärdateien.

Update 30.3.2019: Swift 5 ist offiziell im Docker-Hub angekommen.

Neu in Swift 5 weiterlesen

Unter Ubuntu alte Snap-Pakete löschen

Über den exorbitaten Speicherbedarf von Ubuntus Paketverwaltungsprogramm Snap habe ich ja schon öfters gelästert. Aber erst jetzt ist mir eine weitere unangenehme Eigenheit aufgefallen: Snap speichert standardmäßig von jedem installierten Paket zwei Backups älterer Versionen. Nach Updates bleiben also ältere Versionen erhalten. Das verdreifacht den von Snap beanspruchten Speicherplatz!

Unter Ubuntu alte Snap-Pakete löschen weiterlesen

NULL-Test mit PyMySQL

Die SQL-Syntax unterscheidet syntaktisch bei Vergleichen mit realen Werten und NULL:

SELECT * FROM tabelle WHERE spalte=0
SELECT * FROM tabelle WHERE spalte IS NULL

Wenn Sie in einem Python-Script mit PyMySQL auf eine MySQL- oder MariaDB-Datenbank zugreifen und dabei Datensätzen selektieren möchten, deren Inhalt je nach Parameter auch NULL sein darf, führt das zu Problemen:

import pymysql.cursors
conn = pymysql.connect(...)
with conn.cursor() as cur:
    sql = 'SELECT * FROM tabelle WHERE spalte = %s'
    cur.execute(sql, (0))      # OK
    cur.execute(sql, (None))   # liefert einen SQL-Syntaxfehler
    ...

Lösung

Die naheliegende Lösung besteht darin, das SQL-Statement eben in Abhängigkeit vom betreffenden Parameter zu variieren, also:

if value == None:
    sql = 'SELECT * FROM tabelle WHERE spalte IS %s'
else:    
    sql = 'SELECT * FROM tabelle WHERE spalte = %s'

In einem Projekt musste ich zuletzt aber eine Menge derartiger SELECT-Abfragen zusammenstellen, bei denen es jeweils viele Parameter gab, die alle NULL sein konnten. Der obige Ansatz wird dann unübersichtlich. Ich habe mir deswegen eine kleine Funktion programmiert, an die ich ein Dictionary mit Spaltennamen und Werten übergeben kann. Die Funktion erzeugt daraus eine Zeichenkette mit dem WHERE-Teil des SQL-Statements.

dict = { 'spalte1': 123, 'spalte2': 'abc', 'spalte3': None }
sql = 'SELECT FROM tabelle ' + buildWhere(conn, dict)

# erzeugt eine Zeichenkette der Form
# WHERE col1 = 'val1' AND col2 = 'val2' etc.
# mit   col1 IS NULL für Werte, die None sind
def buildWhere(conn, dict):
    result = "WHERE "
    for colname, value in dict.items():
        if value == None:
            result += colname + ' IS NULL AND '
        else:
            result += colname + ' = ' + conn.escape(value) + ' AND '

    return result[:-4]  # letztes 'AND ' eliminieren

Die Methode escape stellt sicher, dass das auch dann funktioniert, wenn die Werte im Dictionary Anführungszeichen oder andere problematische Zeichen enthalten.

Ergänzung 21.12.2018

Wenn die zu vergleichenden Daten (betrifft nur Zeichenketten) das Zeichen % enthalten, glaubt PyMySQL bei der Verarbeitung des SQL-Kommandos, an dieser Stelle seien Parameter einzusetzen. Abhilfe: Ersetzen Sie das Prozentzeichen durch zwei derartige Zeichen, also:

def buildWhere(conn, dict):
    ...
    result = result.replace('%', '%%')
    return result[:-4]  # letztes 'AND ' eliminieren

Quellen: https://stackoverflow.com/questions/3037581, http://mysql-python.sourceforge.net/MySQLdb.html#functions-and-attributes