Ansible startet nicht mehr unter Mac OS Catalina

Beim Ausführen von Ansible Befehlen bekam ich seit kurzem immer wieder die Fehlermeldung

Abort trap: 6

angezeigt. Da ich Ansible direkt über pip installiert hatte, führte ich natürlich erstmal ein Update dort durch – was aber keine Abhilfe brachte. Irgendwie hatte das ganze mit dem Wegfall von python 2.7 mit Mac OS Catalina zu tun.

Die relativ plumpe, aber doch effektive Lösung war:

pip3 uninstall ansible
brew install ansible

🤷‍♂️😂

Freenas Jail meldet, dass das Shared Object libdl.so.1 fehlt

Beim Herumspielen mit einem neuen Jail in meiner Freenas Instanz konnte ich zwar alle möglichen Packages installieren, jedoch meldeten die diversen Tools immer wieder folgendes (in diesem Fall bei python3):

Shared object "libdl.so.1" not found, required by "python3.5"

 

Soweit ich es herauslesen konnte, liegt das wohl an ein paar umgebauten Paketen im aktuellen Freenas Jail Template, weswegen es zu dieser Unstimmigkeit kommt. Um das Problem vorerst zu lösen, kann man sich mittels eines kleinen Downgrades behelfen:

  • die Datei “/usr/local/etc/pkg.conf” bearbeiten und in der ersten Zeile folgendes hinzufügen:
    set OSVERSION = 1101001
  • in der Datei /etc/pkg/FreeBSD.conf die Property “url” auf folgendes ändern:
    url: "pkg+http://pkg.FreeBSD.org/${ABI}/release_2",
  • in der Datei /usr/local/etc/pkg/repos/FreeBSD.conf die Property “url” auf folgendes ändern:
    url: "pkg+http://pkg.FreeBSD.org/freebsd:11:x86:64/release_2",
  • und dann mittels folgender Befehle das Downgrade starten:
    pkg update -f
    pkg upgrade -f

Alle aufkommenden Fragen mit y bestätigen, und schon sollten Python und co wieder laufen.

Quelle: forums.freenas.org

python pip läuft nicht mehr wegen OpenSSL lib Fehler

Heute hat mich pip mit der Fehlermeldung

AttributeError: 'module' object has no attribute 'SSL_ST_INIT'

begrüßt. Da nach diesem Fehler sämtliche pip Operationen nicht mehr funktionieren, muss man etwas nachhelfen. Genauer gesagt: zwei Python OpenSSL Module müssen entfernt und nochmal neu installiert werden:

rm -rf /usr/lib/python2.7/dist-packages/OpenSSL
rm -rf /usr/lib/python2.7/dist-packages/pyOpenSSL-0.15.1.egg-info
sudo pip install pyopenssl

Danach sollte pip wieder wie gewohnt funktionieren.

PS: bitte achte drauf, dass du die korrekte Python Version bereinigst, das gleiche gilt für die pyOpenSSL Version!

Am einfachsten findest du die Version heraus, indem du dir per

which pip

den Pfad zu pip geben lässt, dann mit einem vi/nano /[PATH_TO_PIP]/pip in der obersten Zeile anschaust, welcher Interpreter verwendet wird, diesen Pfad kopierst und dann mit

/PATH_TO_PYTHON/python --version

die korrekte Version herausbekommst.

Python MySQL connector liefert in einer Endlossschleife immer das gleiche Query Ergebnis

Für ein Projekt habe ich einen Runner laufen, der in bestimmten Intervallen eine MySQL Datenbank abfragt, ob es neue Jobs für ihn zu tun gibt. Letztendlich handelt es sich einfach um eine Endlos-While-Schleife, in der immer wieder die Query ausgeführt wird.

Das Problem war aber nun: der Runner hat im aktuellen Lauf scheinbar immer nur das Ergebnis des ERSTEN Durchlaufs der Schleife aus dem Cache gelesen. Dabei handelt es sich wohl nicht um einen Fehler auf Python Seite, sondern in MySQL selbst. Die Lösung ist zwar technisch nicht gerade schön gelöst, aber sie funktioniert: man muss einfach nur die Autocommit-Funktion für die aktuelle Verbindung zum MySQL Server aktivieren. Und das geht so:

cnx = mysql.connector.connect(...)
cnx.autocommit = True

Durch dieses Setting wird dem MySQL Server ein “set autocommit=1;” übertragen, was dann dazu führt, dass der Query Cache komplett umgangen wird.

Wie lade ich in Django 1.10 ein Bild von der Festplatte per Django Command hoch?

Für den Fall, dass man ein Bild in eine Django Applikation uploaden möchte, gibt es unzählige Tutorials – kniffelig wird es dann ein bisschen, wenn man ein Bild von der Festplatte des Servers, auf dem die Applikation läuft, mittels Django Command hochladen möchte. In meinem Beispiel importiere ich Bilder per Cronjob aus einem anderen Programm. Bisher ging der Upload auch ohne Probleme, aber seit Django 1.9 oder 1.10 wurde das Sicherheitskonzept geändert – man darf keine Dateien mehr ausserhalb des Media_Path Kontextes hochladen (Suspicious File Operation. Um das Problem zu umgehen, muss man das “normale” Fileobject, welches man normalerweise dann an das Model übergeben würde, in den Django File Wrapper packen. Dazu importiert ihr diesen Wrapper wie im Beispiel unten, übergebt den realen Pfad zum Bild und, und das ist nun wichtig, übergebt per “name” Parameter einen beliebigen Dateinamen, mit dem diese Datei dann im “Upload Prozess” von Django ankommt. Nun müsst ihr das “image” Objekt einfach nur an den Image Parameter eures Models hängen, und schon klappt das Einspielen der Datei wieder. Bei mir war es tatsächlich der fehlende “name” Parameter, der mich in die Verzweiflung getrieben hat 🙂

from django.core.files import File
image = File(open("[PATH_TO_REAL_FILE]", "rb"), name="[SOME_FILE_NAME]")

[Quicktip] Wie kann ich alle installierten Python pip Packages upgraden?

Über einen kleinen Umweg kann man auf der Bash ganz einfach alle aktuell installierten pip Pakete updaten / upgraden:

pip freeze | sed -e 's/==.*//g' > upgrade.txt
pip install --upgrade -r upgrade.txt
rm upgrade.txt

Das Script lässt sich alle installierten Pakete ausgeben, entfernt das “==[Versionsnummer]” hinter dem Namen und packt diese Liste in die Datei upgrade.txt. Anschließend wird diese Datei bei einem “pip upgrade” als “requirements.txt” übergeben und mit dem upgrade Befehl ausgeführt.

Readme driven Design – das etwas andere Pattern

Letzte Woche fiel mir ein sehr interessanter Beitrag (How I Develop Things and Why) zum Thema Entwicklungsstil in die Hände. Der Autor, Kenneth Reitz, vertrat dabei die Meinung, dass man alles sinnvoll designen sollte. Das mag jetzt zwar logisch klingen, ist es aber nicht. Wenn Entwickler von Design sprechen, dann ist meist das Design für den Endkunden gemeint. Die gleichen Regeln sollten aber auch für alle anderen gelten. Sprich, auch ein API oder eine Library sollte intuitiv und nutzerfreundlich sein.

Keneth, selbst ein bekennender Python Fan, geht darauf am Beispiel der http Library für eben diese Sprache ein. Sie tut zwar was sie soll, nervt den Entwickler aber mit unzähligen kryptischen Parametern und viel Schreibaufwand für einfachste Aufgaben. Um diesen Umstand zu verbessern, hat er eine Library geschrieben, die als Schnittstelle zwischen dem Entwickler und der ursprünglichen Library sitzt – spirch, ein Wrapper.

Und somit kommen wir zum Kern dieses Beitrages: Als Designphilosophie für diesen Wrapper wählte er das “Readme driven design”. Häh? So in etwa habe ich auch geschaut, als ich es zum ersten mal las. Das Prinzip ist aber recht sinnvoll: in der normalen Entwicklung fängt man mit einer simplen Idee an, baut das entsprechende API und alles ist toll. Nachdem die Grundfunktionen stehen, erweitert man das ganze, passt das API ein bisschen an, refactored ein bisschen, wieder wird das API angepasst usw. Irgendwann hat man zwar eine Library (bzw. ein Tool), die alles mögliche kann, was aber wiederum mit dem ursprünglichen API-Design nicht mehr realisierbar gewesen wäre. Heraus kommt dann ein Konstrukt aus undurchsichtigen Parametern und umständlichen Vorgehensweisen, um das gewünschte Ergebnis zu erhalten.

Die bessere Alternative ist nun folgende: man schreibt zuallererst die Readme Datei inkl. ausführlicher Syntax und Beispielen – genau so, als ob das Stückchen Software bereits existieren würde und fertig wäre. Und erst dann beginnt man mit der Umsetzung. Der Vorteil ist nun, dass man das API so designt hat, wie man gern damit arbeiten würde – unabhängig von auftretenden Hürden und Problemen. In der Regel sollte ein großer Teil der Entwickler in dieser Hinsicht ein gleiches Verständnis von “leicht” haben. Hinzu kommt: man “überdesignt” nicht – denn der Funktionsumfang ist ja nun genau definiert.

Wie man bereits feststellen kann, eignet sich diese Methode natürlich nicht für große Projekte – dafür macht sie für kleine Scripte oder Libraries umso mehr Sinn.

Was haltet ihr davon? Sinnvoll, oder Quatsch? Oder konntet ihr bereits Erfahrung damit sammeln?