Aus Linux-Magazin 03/2017

Amazon Web Services einrichten – Teil 2 (Seite 2)

RAM ist Geld

Wie holt ein Python-Programmierer nun ein Dokument vom Web? Ein erster Ansatz wäre die Methode »read()« nach einem »urlopen()«, die alle so eingeholten Bytes gleich wieder mittels »write()« in eine lokale Datei schreibt. Aber das hätte zur Folge, dass eine eventuell große Videodatei komplett in den Arbeitsspeicher gelesen würde, bevor Python sie dann auf die Platte schreibt.

Die damit nötige üppige Versorgung mit RAM kostet aber Geld auf Amazon, also verwendet Listing 2 die Methode »urlretrieve()« aus dem Modul »urllib«, die – hoffentlich mehr oder weniger intelligent – stückweise puffern kann.

Listing 2

vimo.py

01 #!/usr/bin/python
02 import urllib
03 import tempfile
04 import shutil
05 import subprocess
06 import boto3
07 import os
08
09 def lambda_handler(event, context):
10     tmpd = tempfile.mkdtemp()
11
12     # fetch movie
13     movie_url  = event['movie_url']
14     movie_file = os.path.join(tmpd,
15         os.path.basename(movie_url))
16     urllib.urlretrieve(movie_url,movie_file)
17
18     # motion analysis
19     print subprocess.check_output([
20         "bin/max-movement-lk.py",
21         movie_file])
22
23     # generate montage
24     print subprocess.check_output([
25         "bin/mk-montage.py",tmpd])
26
27      # store montage in s3
28     s3 = boto3.resource('s3')
29     bucket = "snapshot.linux-magazin.de"
30     data = open(os.path.join(
31          tmpd,'montage.jpg')).read()
32     s3.Bucket(bucket).put_object(
33         Key="montage.jpg",
34         Body=data,ContentType="image/jpeg")
35
36     result = { "montage_url":
37       "https://s3-us-west-2.amazonaws.com" +
38       "/snapshot.linux-magazin.de/" +
39       "montage.jpg"}
40
41     shutil.rmtree(tmpd)
42     return result

Zwiespalt: Python 2 und 3

Die Python-Welt leidet unter den Gegensätzlichkeiten zwischen Python 2.x und 3. Letzteres stellt eine Art paradiesischen Zustand dar, in dem Kinderkrankheiten behoben und Unstimmigkeiten bereinigt sind und coole Neuentwicklungen stattfinden. Nur nutzt kaum jemand Python 3 in Produktionsumgebungen, auch Amazon bietet nur 2.7 an.

In Python 2.x schlägt sich der Programmierer mit hanebüchenem Wildwuchs an Libraries herum und muss sich etwa beim Holen von Webdaten zwischen den inkompatiblen Erzeugnissen »urllib« und – kein Scherz – »urllib2« entscheiden. Wer externe Programme starten möchte, nutzt in 2.x »check_output()« des Moduls »subprocess«, während in Python 3.x die Methode »run()« andere Parameter verwendet und »check_output()« nicht mal mehr existiert.

Lambda Go

Die Lambda-Funktion in Listing 2 bekommt die URL der zu analysierenden Videodatei im Parameter-Dictionary »event« unter dem Schlüssel »movie_url« zugespielt. In einer echten Produktionsumgebung darf kein Python-Skript in einem festen Verzeichnis wie »data« operieren und hoffen, dass niemand dazwischenfunkt. Da Amazon-Lambda-Funktionen parallel aufgerufen werden, müssen sie für solche Zwecke mit Pythons »tempfile«-Modul zunächst ein Instanz-eigenes temporäres Verzeichnis anlegen und nach Abschluss der Tätigkeit wieder abräumen.

Damit dies auch passiert, falls eine der Funktionen nach einem Fehler eine Exception auswirft, sollte die letzte Zeile im Produktionsbetrieb in einem Exception-Handler stehen, das unterblieb in der Testversion. Listing 2 ruft in Zeile 10 die Methode »mkdtemp()« auf und nutzt das neue Verzeichnis, um in Zwischenschritten ermittelte Daten für die nächsten Stufen des Skripts abzulegen.

So legt Zeile 16 die per Webrequest eingeholte Videodatei unter dem in der Variablen »movie_file« abgelegten Namen ab, der aus dem letzten Teil des Pfads der URL stammt. Als nächste Stufe ruft Zeile 19 das Skript »max-movement-lk.py« aus dem Listing 3 auf, einen Python-Wrapper um das C++-Programm in Listing 1, und übergibt ihm den Pfad zur Videodatei im temporären Verzeichnis.

Listing 3

max-movement-lk.py

01 #!/usr/bin/python
02 import sys
03 import os
04 import subprocess
05
06 top_dir    = os.getcwd()
07 movie_path = sys.argv[1]
08
09 os.chdir(os.path.dirname(movie_path))
10
11 os.environ["LD_LIBRARY_PATH"] = os.path.join(top_dir,"lib")
12
13 print subprocess.check_output(
14   [ os.path.join(top_dir, "bin/max-movement-lk") ] +
15   [ os.path.basename(movie_path) ] )

Auf Montage

Hinterlässt die Analyse eine Reihe von Jpegs im Format »0001.jpg«, »0002.jpg«, …, kommt in der nächsten Stufe ab Zeile 24 in Listing 2 das Wrapperskript »mk-montage.py« in Listing 4 zum Zuge, das in die Dateinamen eingebettete Sekundenwerte ins Format »SS::MM:ss« umwandelt und die alten Dateinamen sowie die formatierten Labels Imagemagicks »montage« zu fressen gibt:

Listing 4

mk-montage.py

01 #!/usr/bin/python
02 import glob
03 import subprocess
04 import re
05 import time
06 import os
07 import sys
08
09 dir = sys.argv[1]
10 files = glob.glob(
11        os.path.join(dir,'*.jpg'))
12 cmds  = ["bin/montage.py"]
13
14 r = re.compile('.*?(\d+)')
15
16 for file in sorted(files):
17     match = r.match(file)
18     if match:
19         label = time.strftime("%H:%M:%S",
20           time.gmtime(int(match.group(1))))
21         cmds.append("-label")
22         cmds.append(label)
23         cmds.append(file)
24     else:
25         print "no match: " + file
26
27 cmds.append(os.path.join(
28     dir,'montage.jpg'))
29
30 print subprocess.check_output(cmds)
montage.py -label  00:00:01 tmp/001.jpg  [...]

Das Programm baut daraus einen Kontaktabzug in der Datei »montage.jpg«, die später in Amazons S3 landet, damit User sie per Link auf den Client holen können.

Abbildung 4: Gesammelte Shared Libs.

Abbildung 4: Gesammelte Shared Libs.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben