Seite 1 von 2

ImageMagic convert popen

Verfasst: Sonntag 23. August 2009, 19:51
von Shining-Blue
Hallo allerseits,
ich habe hier ein kleines Problem mit dem Aufruf von convert über subprozess-Popen

folgender Aufruf funktioniert:

Code: Alles auswählen

 os.system(pathtobin + 'convert ' + infile + ' -resize 320x ' + folder + '/thumb_' + infile + ' 1>NUL 2>NUL')
dieser hingegen gibt den Fehler 'Unzulässiger Parameter - 320x' aus

Code: Alles auswählen

 sub.Popen([pathtobin + 'convert', '-resize', '320x', infile, folder + '/thumb_' + infile], shell = False)
ich habe nun schon etliche Varianten der Parameter probiert, doch hier komme ich nicht weiter :(

Ich hoffe jemand von Euch weiß Rat.

LG SB[/code]

Verfasst: Sonntag 23. August 2009, 20:05
von cofi
Kann ich nur nachvollziehen, wenn ich '-resize 320x' statt '-resize', '320x' verwende.
Letzteres funktioniert.

``shell`` ist btw per default `False`.

Verfasst: Sonntag 23. August 2009, 20:41
von Shining-Blue
Das ist ja merkwürdig.
Ich habe gerade noch einmal meinen Code überprüft - bei mir funktioniert das nicht.
Versuche ich die gleiche Zeile unter OS X, so findet er nicht einmal die Dateien.
Die os.system - Variante klappt soweit unter allen Plattformen ohne Probleme, doch wenn ich das Prog dann mit py2exe in eine ausführbare Datei zusammenstellen lasse, bombardiert mich das Programm mit etlichen aufflackernden Shell-/cmd-Fenstern und die nerven gewaltig.
Deshalb der Versuch mit popen und shell=false.
Wenn mir jemand sagen könnte, wie ich die aufblitzenden Fenster los werde, kann ich locker mit der os.system Variante leben.

LG Lena

Verfasst: Sonntag 23. August 2009, 20:48
von problembär
Ich würde mir immer erstmal den String ausgeben lassen, den man an os.system() übergeben will, und den überprüfen. Oft hat man irgendwo ein Leerzeichen oder so vergessen.

Gruß

Verfasst: Sonntag 23. August 2009, 22:11
von Shining-Blue
Mit os.system klappt es ja alles wunderbar.
Unter Linux und Mac werden auch keine Shellfenster aufgemacht und unter Windows nur wenn ich es durch py2exe jage.
Da das Skript aber für Software-DAUs einen Forums sein soll, ist das so leider nicht tragbar.
Deshalb versuche ich ja eine Lösung mit popen hinzubekommen.

LG SB

Verfasst: Sonntag 23. August 2009, 22:43
von BlackJack
@Shining-Blue: Gibt's einen Grund warum Du beim `Popen` plötzlich eine andere Reihenfolge für die Argumente wählst? Kann es vielleicht sein, dass `convert` als erstes die Eingabedatei verlangt, und nun versucht die "Option" `320x` auf die Datei "-resize" anzuwenden!? Und diese Option aber unbekannt ist!?

Verfasst: Montag 24. August 2009, 02:51
von Shining-Blue
Ja, das habe ich mir von einem anderen Beispiel abgeschaut.
Vorher hatte ich die Reihenfolge der Parameter genau so wie es auch bei einem Aufruf von der Shell oder über os.system sein müsste.
In der Reihenfolge convert infile -resize 320x outfile meckert er aber schon über -rezise als ungültigen Parameter.
Ich tüftel da wirklich schon eine ganze Weile rum, aber finde auch sonst im Netz kaum etwas brauchbares.
Wird denn sooo selten ImageMagick direkt aus Python verwendet?
Immerhin gab es doch lange sogar entsprechende Wrapper, die leider nicht mehr weiter entwickelt wurden.
Ich bin schon drauf und drann das alles auf PIL umzuschreiben.
Die Distutils bzw. py2app und py2exe würden ja PIL mit einbinden, so das es für die Endanwender sogar den Vorteil hätte, das sie nicht einmal IM auf seinem System haben müsten.

LG SB

Verfasst: Montag 24. August 2009, 06:30
von BlackJack
Also folgendes funktioniert bei mir:

Code: Alles auswählen

import os
from subprocess import Popen

def main():
    bin_foldername = '/usr/bin/'
    filename = 'test.jpg'
    out_foldername = '/tmp'
    convert_process = Popen([os.path.join(bin_foldername, 'convert'),
                             filename,
                             '-resize', '320x',
                             os.path.join(out_foldername, 'thumb_' + filename)])
    return_code = convert_process.wait()
    if return_code:
        print 'There was a problem.', return_code
@Shining-Blu: Bist Du sicher, dass Du das richtige `convert` ausführst? Vielleicht gibt es auf Deinem System noch ein anderes Programm, dass so heisst. Ist ja kein besonders origineller Name.

Verfasst: Montag 24. August 2009, 08:06
von Shining-Blue
Ich bin mir sicher, daß das richtige convert aufgerufen wird, da eine Funktion zuvor die Existenz überprüft. Wenn ich convert verschiebe wird brav gemeckert. Auch funktioniert es ja mit os.system einwandfrei.
Dein Segment werde ich mir mal genauer ansehen - es ähnelt ja stark meinen ersten Versuchen auf Popen umzustellen.
Der gravierende Unterschied scheint ja das zusammenführen des Pfadnamens mit dem Befehl bzw dem dem Namenszusatz der Ausgabe zu sein.
Wenn das der Trick ist, dann wäre ich da alleine wohl in drei Wochen noch nicht drauf gekommen - werde berichten.

LG SB

Verfasst: Montag 24. August 2009, 09:57
von Shining-Blue
@BlackJack

Dein Codefragment brachte den Durchbruch :)

so funktioniert es nun auch bei mir:

Code: Alles auswählen

convert_process = sub.Popen(
    [os.path.join(pathtobin , 'convert'),
    os.path.join(workpath , infile), '-resize', '640x', 
    os.path.join(workpath , folder , ('small_' + infile))])
return_code = convert_process.wait() 
Ich hatte im ersten Versuch Deine Variante zu übertragen die .wait Zeile unterschlagen, was zu sehr sonderbaren Ergebnissen führte.
Nun bleibt noch abzuwarten, ob sich so die lästigen Shellfenster unter Windoof unterdrücken lassen.

Herzlichen Dank & LG

SB

Verfasst: Montag 24. August 2009, 13:17
von lunar
Ungetestet:

Code: Alles auswählen

import subprocess

cmd = [os.path.join(pathtobin , 'convert'),
           os.path.join(workpath , infile), '-resize', '640x',
           os.path.join(workpath , folder , ('small_' + infile))]
options = {}
if subprocess.mswindows:
    options['startupinfo'] = info = subprocess.STARTUPINFO
    info.wShowWindow = subprocess.SW_HIDE
    options['creationflags'] = subprocess.STARTF_USESHOWWINDOW
subprocess.call(cmd, **options)
Da ich kein Windows zur Verfügung habe, kann ich das auch nicht testen, nach meinem Verständnis der Dokumentation und nach einem Blick in den Quellcode von subprocess müsste es aber funktionieren. Die Dokumentation zu diesen Werten findest Du, wenn Du in der MSDN nach "CreateProcess" suchst. Von dort aus findest Du dann über weitere Links Beschreibungen der Struktur und der erlaubten creationflags-Werte (von denen meines Wissens aber nicht alle durch subprocess zur Verfügung gestellt werden).

Verfasst: Montag 24. August 2009, 16:22
von Shining-Blue
@lunar

Puh Du mutest mir als Newbee aber eine Menge zu :wink:
Ist doch mein Erstlingswerk in Python und meine anderen Programmiererfahrungen beschränken sich auf Pascal, Assembler u.s.w. und stammen noch aus den guten alten 8-Bitter Tagen, wo man noch mit jedem Byte auf Du & Du stand.
Aber ich werde mal versuchen mich durch die angegebene Doku zu wühlen.
Grrr - alles nur wegen dieser dusseligen DOSen :evil:

LG SB

P.S.: Sinnlos läuft bei uns auch nur als Gast-OS unter OS X - das langt dicke

Verfasst: Montag 24. August 2009, 16:38
von cofi
Shining-Blue hat geschrieben:guten alten 8-Bitter Tagen, wo man noch mit jedem Byte auf Du & Du stand
Ich kann nicht anders: http://www.youtube.com/watch?v=4qsWFFuYZYI

Verfasst: Montag 24. August 2009, 16:54
von lunar
Shining-Blue hat geschrieben:Puh Du mutest mir als Newbee aber eine Menge zu :wink:
Verzeihung, aber konnte ich das ahnen? ;)

Verfasst: Montag 24. August 2009, 18:58
von Shining-Blue
@cofi

Absolut cool !
Schon irre was Leute so mit Legosteinen so zaubern können.
Schön das Du nicht anders konntest.

LG SB

Oh Gnaade

Verfasst: Montag 24. August 2009, 19:08
von Shining-Blue
Zitat aus MS-Doku:
....
Eine möglicherweise davon aus, die an die erstellte Anwendung übergebenen Befehlszeile ein zusammengesetztes der Anwendungsname und CommandLine-Parameter ist, aber dies nicht der Fall ist.
... u.s.w.

Aua, das ist ja jenseits jeglicher Verständlichkeitsgrenze :x

LG SB

Verfasst: Montag 24. August 2009, 23:11
von Shining-Blue
Es wäre ja auch zu schön um wahr zu sein, aber ein Viraus aus Redmond muß einem mal wieder die Suppe versalzen :(
Natürlich läuft das, was wir uns bisher ausgetüftelt haben unter Mac und Linux einwandfrei, aber unter Windows geht so überhaupt nichts mehr.
Wenn man nicht in das "Pfad mit Leerstellen" Problem läuft (liegt nicht einer der häufigsten unter "Dokumente und Einstellungen"???), dann wird das letzte Pfadelement als ungültiger Parameter angemahnt.
Ich glaube ich schweinke wirklich mal auf den PIL-Ansatz um.
Mit Popen Plattformubergreifend zu arbeiten scheint doch arg kniffelig - schade eigentlich.

LG SB

Verfasst: Dienstag 25. August 2009, 06:57
von BlackJack
@Shining-Blue: Das verstehe ich jetzt nicht. Mit `Popen()` hat man wesentlich weniger Probleme mit Leerzeichen in Argumenten als Beispielsweise mit `os.system()`. Man braucht nichts mehr zu "escapen" und kann den Pfad genau so hinschreiben, wie er auch heisst.

Verfasst: Dienstag 25. August 2009, 08:52
von lunar
@BlackJack: Das kann schon sein. "subprocess" benutzt unter Windows "CreateProcess". Diese Funktion nimmt allerdings eine Zeichenkette mit der Befehlszeile entgegen. "subprocess" behilft sich damit, übergebene Listen mittels "subprocess.list2cmdline()" in eine Zeichenkette umzuwandeln. Das geht natürlich schief, wenn das Programm andere, unerwartete Regeln zum Parsen der Argumente nutzt. Dieses Verhalten ist auch dokumentiert.

Allerdings kann man das nicht subprocess anlasten, sondern dem abenteuerlichen Design der Windows-API. Andere Bibliotheken und Rahmenwerke wie Qt oder das JRE dürften das selbe Problem haben.

@Shining-Blue: Rufe doch unter Windows mal manuell "subprocess.list2cmdline()" mit deiner Liste aus und lass dir dessen Rückgabewert anzeigen. Vielleicht erkennst Du ja wo der Fehler liegt.

Verfasst: Dienstag 25. August 2009, 10:22
von Shining-Blue
Das war eine gute Idee.

Code: Alles auswählen

print sub.list2cmdline([os.path.join(pathtobin , 'convert'), os.path.join(workpath , infile), '-resize', '320x', os.path.join(workpath , folder , ('thumb_' + infile))])
ergibt die Consolenausgabe

Code: Alles auswählen

convert "C:/Dokumente und Einstellungen/Lena/Desktop/aaaaa/test_2.JPG" -resize 3
20x "C:/Dokumente und Einstellungen/Lena/Desktop/aaaaa/test_2\thumb_test_2.JPG"
Unzulässiger Parameter - /Dokumente
So wie es scheint werden die Pfaddelimeter nicht wingerecht auf C:\Dokumente und Einstellungen\Lena\Desktop\aaaaa umgesetzt.

Die os.xxx und shutils machen dies jedoch richtig.

Wäre is im Sinne einer einfacheren, plattformübergreifenden Weitergabe nicht sinnvoller ganz auf externe Programme ala ImageMagick zu verzichten und dafür die PIL zu nutzen?
Der Ansatz mit ImageMagick stammt noch aus dem Ursprung des Scripts als Shellscript. Von der Pil habe ich erst im Laufe der "Entwicklung" dieses kleinen Progs erfahren.
Ich glaube ich könnte mir so gleichzeitig mehere Probleme vom Hals schaffen.
Auf der anderen Seite ist es natürlich äußerst unbefriedigend an einer so simplen Aufgabe wie der plattformübergreifenden Ausführung eines externen Befehls zu scheitern :cry:

LG SB