Hallo,
ich bin gerade dabei mich in Python einzuarbeiten und neu hier im Forum.
Mittels des kleinen Tools lsdvd (http://wiki.ubuntuusers.de/lsdvd) kann man Infos zu einer eingelegten DVD auslesen.
Dabei gibt es auch die Möglichkeit mit dem Befehl:
lsdvd Pfad -Oy
das ganze als Python-Dictionary formatiert auszugeben. Meine Frage ist jetzt, wie ich an diese Werte tatsächlich herankomme?
Wenn ich den Befehl mit os.system aufrufe erhalte ich nur eine 0 als Rückgabewert, oder habe ich da was übersehn?
Muss ich die Ausgabe erst in eine Datei schreiben, und die dann wieder einlesen?
Würde mich über eure Hilfe freuen!
Rückgabe von lsdvd in Python einlesen
Hallo BlackJack,
danke für den Tip mit subprocess!
Habe es grad mal probiert (angelehnt an ein Beispiel im Netz):
Der Inhalt von Info ist dann allerdings auch nur ein String. Irgendwie steh ich auf dem Schlauch wie ich auf die Ausgabe als dictionary zugreifen kann?
danke für den Tip mit subprocess!
Habe es grad mal probiert (angelehnt an ein Beispiel im Netz):
Code: Alles auswählen
DVD = subprocess.Popen("lsdvd -Oy" Pfad, shell=True, stdout=subprocess.PIPE)
Info = DVD.communicate()[0]
@Marc_4: Als erstes solltest Du das mal ohne unnötige Shell aufrufen.
Mit `ast.literal_eval()` kann man die Zeichenkette *sicher* in eine Python-Datenstruktur überführen.
Mit `ast.literal_eval()` kann man die Zeichenkette *sicher* in eine Python-Datenstruktur überführen.
Hallo BlackJack,
wenn ich es ohne Shell aufrufe erhalte ich eine Fehlermeldung:
OSError: [Errno 2] No such file or directory: 'lsdvd -Oy /media/Multimedia/Laptop/BB/1-1'
Obwohl das Verzeichnis existiert.
Ich glaub langsam mein Vorhaben ist etwas zu komplex für meine noch bescheidenen Kenntnisse...
wenn ich es ohne Shell aufrufe erhalte ich eine Fehlermeldung:
OSError: [Errno 2] No such file or directory: 'lsdvd -Oy /media/Multimedia/Laptop/BB/1-1'
Obwohl das Verzeichnis existiert.
Ich glaub langsam mein Vorhaben ist etwas zu komplex für meine noch bescheidenen Kenntnisse...
Hallo.
Wenn man dir einen Hinweis auf eine Funktion gibt, dann solltest du diese nicht einfach blind benutzen, sondern einen Blick in die Dokumentation riskieren Der erste Parameter von Popen sollte eine Liste von Argumenten sein und kein String:
Nun kannst du denn shell-Parameter weglassen, da die Shell nichts mehr interpretieren muss.
Wenn man dir einen Hinweis auf eine Funktion gibt, dann solltest du diese nicht einfach blind benutzen, sondern einen Blick in die Dokumentation riskieren Der erste Parameter von Popen sollte eine Liste von Argumenten sein und kein String:
Code: Alles auswählen
["lsdvd", "-Oy", "/media/Multimedia/Laptop/BB/1-1"]
Das Leben ist wie ein Tennisball.
Hallo & Danke!
Konnte das Problem jetzt soweit lösen.
Hab ich das in der Doku zu subprocess richtig verstanden, das man in der Liste mit übergebenen Argumenten auch die jeweilige Option und ihr zugehöriges Argument als einzelnes Listenobjekt übergibt? Also in der Form:
Meine Lösung für das Einlesen der Track-Anzahl auf der jeweiligen DVD sieht jetzt so aus, für etwaige Kritik/Anregungen wäre ich dankbar!
Konnte das Problem jetzt soweit lösen.
Hab ich das in der Doku zu subprocess richtig verstanden, das man in der Liste mit übergebenen Argumenten auch die jeweilige Option und ihr zugehöriges Argument als einzelnes Listenobjekt übergibt? Also in der Form:
Code: Alles auswählen
["avconv", "-i", "Input.flv", "-vcodec", "libx264"]
Meine Lösung für das Einlesen der Track-Anzahl auf der jeweiligen DVD sieht jetzt so aus, für etwaige Kritik/Anregungen wäre ich dankbar!
Code: Alles auswählen
RawDvdList = os.listdir(RawDvdPath)
for DvdNumber, DvdName in enumerate(RawDvdList):
DvdInfo = subprocess.Popen(["lsdvd", "-Oy", "/home/user/DVDs/" + DvdName], stdout=subprocess.PIPE)
# exec() erzeugt eine Dictionary-Variable mit dem Namen lsdvd
exec(DvdInfo.communicate()[0])
Tracks = len(lsdvd.get("track"))
print(Tracks)
@Marc_4: warum gibst Du im os.listdir das Verzeichnis über RawDvdPath an und beim Subprocessaufruf direkt als "/home/user/DVDs/"?
Der direkte Aufruf von exec mit Strings aus externen Quellen ist ein Scheunentor großes Sicherheitsrisiko. Warum benutzt Du nicht, wie von Blackjack vorgeschlagen ast.literal_eval?
Der direkte Aufruf von exec mit Strings aus externen Quellen ist ein Scheunentor großes Sicherheitsrisiko. Warum benutzt Du nicht, wie von Blackjack vorgeschlagen ast.literal_eval?
@Marc_4: Das ``exec`` ist gruselig. Da wird beliebiger Code der von einem externen Programm kommt einfach so ausgeführt. Und das obwohl man eigentlich nur ganz einfache Daten haben möchte, also etwas was mit deutlich weniger Sicherheitsrisiko passieren kann und sollte. Ich würde da entweder das 'lsdvd =' weglassen und den Rest *sicher* mit der Funktion aus dem `ast`-Modul parsen oder eine andere Ausgabe bei dem externen Werkzeug wählen, zum Beispiel XML.
Die Namensgebung weicht vom Style Guide for Python Code ab.
`DvdNumber` wird gar nicht verwendet.
Statt ``lsdvd.get('track')`` hätte ich ``lsdvd['track']`` geschrieben. Falls dieser Schlüssel nicht existiert, ist die Fehlermeldung eindeutiger.
`Tracks` hätte ich `track_count` genannt, denn der Name steht ja nur für die Anzahl der Tracks und nicht für die Tracks selber.
Es gibt einmal `RawDvdPath` und dann den literalen Wert '/home/user/DVDs/' wo ich mal vermute, dass die identisch sind!? Pfade sollte man mit `os.path.join()` und nicht mit ``+`` zusammensetzen.
Die Namensgebung weicht vom Style Guide for Python Code ab.
`DvdNumber` wird gar nicht verwendet.
Statt ``lsdvd.get('track')`` hätte ich ``lsdvd['track']`` geschrieben. Falls dieser Schlüssel nicht existiert, ist die Fehlermeldung eindeutiger.
`Tracks` hätte ich `track_count` genannt, denn der Name steht ja nur für die Anzahl der Tracks und nicht für die Tracks selber.
Es gibt einmal `RawDvdPath` und dann den literalen Wert '/home/user/DVDs/' wo ich mal vermute, dass die identisch sind!? Pfade sollte man mit `os.path.join()` und nicht mit ``+`` zusammensetzen.
Hallo,
danke für eure Anregungen!
Den Style Guide werde ich mir bei Gelegenheit mal zu Gemüte führen, im Moment fehlt mir da einfach die Zeit.
DvdNumber soll noch eine Verwendung finden, hätte aber aus dem Beispiel rausgekonnt.
Das mit dem Pfad war mir gar nicht aufgefallen, ich kann aber wirklich in beiden Fällen die Variable nutzen und os.path.join() ist auch sehr nützlich.
Hab jetzt soweit alles angepasst, allerdings funktioniert es mit ast.literal_eval nicht, ich erhalte folgende Fehlermeldung:
ValueError: malformed node or string: b"{\n 'device' : '/media/Multimedia/Laptop/BB/1-1',\n 'title' : 'unknown',\n 'vmg_id' : 'DVDVIDEO-VMG',\n 'provider_id' : '',\n 'track' : [\n {\n 'ix' : 1,\n 'length' : 3344.130,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n {\n 'ix' : 2,\n 'length' : 2775.130,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n {\n 'ix' : 3,\n 'length' : 2774.020,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n ],\n 'longest_track' : 1,\n}\n"
Kann es sein das er mit den Steuerzeichen der Zeilenumbrüche Probleme hat?
danke für eure Anregungen!
Den Style Guide werde ich mir bei Gelegenheit mal zu Gemüte führen, im Moment fehlt mir da einfach die Zeit.
DvdNumber soll noch eine Verwendung finden, hätte aber aus dem Beispiel rausgekonnt.
Das mit dem Pfad war mir gar nicht aufgefallen, ich kann aber wirklich in beiden Fällen die Variable nutzen und os.path.join() ist auch sehr nützlich.
Hab jetzt soweit alles angepasst, allerdings funktioniert es mit ast.literal_eval nicht, ich erhalte folgende Fehlermeldung:
ValueError: malformed node or string: b"{\n 'device' : '/media/Multimedia/Laptop/BB/1-1',\n 'title' : 'unknown',\n 'vmg_id' : 'DVDVIDEO-VMG',\n 'provider_id' : '',\n 'track' : [\n {\n 'ix' : 1,\n 'length' : 3344.130,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n {\n 'ix' : 2,\n 'length' : 2775.130,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n {\n 'ix' : 3,\n 'length' : 2774.020,\n 'vts_id' : 'DVDVIDEO-VTS',\n },\n ],\n 'longest_track' : 1,\n}\n"
Kann es sein das er mit den Steuerzeichen der Zeilenumbrüche Probleme hat?
@Marc_4: Nein, die Funktion will eine Zeichenkette haben, sagt die Fehlermeldung ja auch, und Du übergibst ein Objekt vom Typ `bytes`. Das musst Du dekodieren.
Code: Alles auswählen
import ast
source = "/dev/sr0"
DvdInfo = subprocess.Popen(["lsdvd", "-Oy", source], stdout=subprocess.PIPE).communicate()[0]
dicString = '='.join(DvdInfo.split('=')[1:]).strip()
# oder einfacher, aber festverdrahtet:
#dicString = DvdInfo[8:]
dvdDic = ast.literal_eval(dicString)
print "Titel:", dvdDic["title"]
Code: Alles auswählen
dicString = DvdInfo[8:]
sie fehlschlägt, wenn die Ausgabe von lsdvd nicht
Code: Alles auswählen
lsdvd = {...}
Code: Alles auswählen
ld = {...}
Code: Alles auswählen
dicString = DvdInfo.split('=',1)[1]