Konsolen Programm ausführen und dessen Output in GUI ausgebe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Michael.Klank@tiscali.de
User
Beiträge: 5
Registriert: Dienstag 12. September 2006, 22:24

Hallo Alle Zusammen,

also als erstes, ich habe jetzt 3 Tage gesucht und getestet aber nicht hat mich weitergebracht. Deshalb jetzt hier mein Problem.

Ich möchte ein Programm erstellen,das unter Windows eine Image Datei auf eine CF Disk kopieren. Dafür gibt es "dd" für Windows, welches ein Konsole Programm ist und über Parameter gesteuert wird. Dieses will ich über eine grafische Oberfläche fernbedienen. Dieses "dd" hat ein Parameter "--progress" was auf die stdout den Fortschritt ausgibt. Diese Fortschrittausgabe will ich auswerten. Aber alles was ich auch probiert habe, immer blockiert das Programm die Ausgabe. D.h. ich kann den Output von stdout nicht lesen. Hier ein kleines Testskript:

Code: Alles auswählen

#!/usr/bin/python 
# -*- coding: UTF-8 -*- 
import sys
from subprocess import Popen, PIPE, STDOUT 
cmd = 'c:/Programme/dd/dd.exe if=c:/tmp/python/Test_Image of=\\\\?\\Device\\Harddisk1\\Partition0 bs=1M count=512 --progress'
process = Popen(cmd, stdout=PIPE, stderr=STDOUT) 
for line in process.stdout:
	process.stdout.flush()
	print line
Ich wäre sehr Dankbar für jede Hilfe!!!

Mit freundlichen Grüßen

Michael Klank
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Schau die mal das an:
http://www.python-forum.de/topic-2875.html
http://www.python-forum.de/topic-4941.html

Ich weiß zwar nicht ob du da die Lösung finden wirst, aber vielleicht...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Kannst Du `dd` nicht einfach in Python implementieren? Ungefähr so (ungetestet):

Code: Alles auswählen

def copy_with_progress(source_file, target_file, blocksize, count):
    for i in xrange(count):
        target_file.write(source_file.read(blocksize))
        yield (1.0 / (float(count) / (i+1))) * 100

for percent_done in copy_with_progress(...):
    print '\r%6.2f done.' % percent_done
    sys.stdout.flush()
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

dd schreibt doch nicht einfach eine Datei auf den USB-Stick... Sonder schreib ein Image zurück, oder hab ich da was falsch verstanden???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Jain. `dd` kopiert blockweise von einer Datei in eine andere. Wenn man als Quelle eine normale Datei und als Ziel eine Datei nimmt, die eine ganze Partition oder Platte repräsentiert, dann kopiert man ein Image.

Schau Dir mal das Ziel von `dd` im Ursprungsbeitrag an: Das ist die Windowsvariante von `/dev/hdb`.
Michael.Klank@tiscali.de
User
Beiträge: 5
Registriert: Dienstag 12. September 2006, 22:24

So komme gerade erst von der Arbeit. :cry: Danke für die Antworten. Die beiden Links kenne ich schon, hilft alles nicht. :x Die Idee mit dem selber implementieren von "dd" ist gar nicht so schlecht. Ich werde das mal prüfen. Ich hoffe das es wirklich so einfach ist. Wenn ich eine funktionierende Version habe werde ich die hier vorstellen. Wenn sonst noch jemand eine andere Idee hat, immer her damit.

Mit freundlichen Grüßen

Michael Klank
Michael.Klank@tiscali.de
User
Beiträge: 5
Registriert: Dienstag 12. September 2006, 22:24

Also ich bin es nochmal. Die Idee mit dem selber implementieren von "dd" ist dann doch nicht so einfach :cry:. Unter Linux würde dies wahrscheinlich gut funktionieren aber nicht unter Windows. Hier sind die Laufwerke nicht wie eine Datei ansprechbar bzw. schreibbar. Das "dd" erzeugt ein Blockdevice unter Windows auf welches es schreibt. Aber wie ich das in Python machen kann, weiß ich nicht. Vielleicht hat jemand dazu eine Idee? Ich bin für jede auch noch so kleine Anregung dankbar!!!

Mit freundlichen Grüßen

Michael Klank
BlackJack

Laut diesem Artikel kann man auch unter Windows direkt auf "raw disks" zugreifen:

http://support.microsoft.com/kb/q100027/
Michael.Klank@tiscali.de
User
Beiträge: 5
Registriert: Dienstag 12. September 2006, 22:24

Hallo Leute,

der Tip von BlackJack war Gold wert. Für die Leute die es Interessiert hier ein kleines Testskript welches ein Image auf einen Datenträger schreibt. Es wird später in meine eigentliche Applikation integriert. Ich bin nähmlich gerade am überdenken ob ich PyQt oder wxPython nehmen soll. Auch hier bin für Tipps jeder Art offen und Dankbar. Für Verbesserungsvorschläge des Testskript bin ich natürlich auch immer offen.

Code: Alles auswählen

#!/usr/bin/python 
# -*- coding: UTF-8 -*- 
import sys

def copy_with_progress(source_file, target_file, blocksize, count):
	try:
		file_target = open(target_file, 'r+b')
		try:	
			file_source = open(source_file, 'rb')
		except:
			return -1
		count1 =0
		for i in xrange(count):
			file_target.write(file_source.read(blocksize))
			count1 =  (1.0 / (float(count) / (i+1))) * 100
			print "\rPercent: %3.2f done" % count1
		try:
			file_target.close()
		except:
			return -2
		try:
			file_source.close()
		except:
			return -3
		return 0
	except:
		return -4

source = 'c:/tmp/python/boot.img' 
destination='\\\\.\\f:'

ret = copy_with_progress(source, destination,512000, 1000) 
if int(ret) == -1:
	print 'Can not open source_file: %s' % source
elif int(ret) == -2:
	print 'Can not close target_file %s' % destination
elif int(ret) == -3:
	print 'Can not close source_file %s' % source
elif int(ret):
	print 'Can not open target_file %s' % destination

Nochmals vielen Dank für die gute und KOMPETENTE Hilfe hier.
Danke!!!

Mit freundlichen Grüßen

Michael Klank
BlackJack

Die Ausnahmen durch "Fehlercodes" zu ersetzen ist irgendwie ganz furchtbar. Ausnahmen wurden doch gerade erfunden um Fehlercodes loszuwerden.
Michael.Klank@tiscali.de
User
Beiträge: 5
Registriert: Dienstag 12. September 2006, 22:24

Sehe ich ein. Hab aber noch nicht so viel Erfahrung im Umgang mit Ausnahmen. Wenn Du mir mein Beispiel abändern könntest, so dass ich die Ausnahmen auswerten kann, wäre ich Dir sehr dankbar.

Mit freundlichen Grüßen

Michael Klank
BlackJack

Ungetestet:

Code: Alles auswählen

from __future__ import division
import sys

def copy_file_with_progress(source_file, target_file, blocksize, count):
    for i in xrange(count):
        file_target.write(file_source.read(blocksize))
        yield (1 / (count / (i+1))) * 100

def test():
    source_name = 'a.dat'
    target_name = 'b.dat'
    try:
        try:
            source_file = open(source_name, 'rb')
            try:
                target_file = open(target_name, 'r+b')
                for percentage in copy_file_with_progress(source_file,
                                                          target_file,
                                                          1024 * 1024,
                                                          512):
                    sys.stderr.write('\rPercent: %3.2f done' % percentage)
                    sys.stderr.flush()
                sys.stderr.write('\n')
            finally:
                target_file.close()
        finally:
            source_file.close()
    except IOError, error:
        print error
Ich habe das öffnen der Dateien und die Prozentausgabe aus der Kopierfunktion wieder herausgezogen. Bei den Dateien hat man so mehr Freiheiten was genau man übergibt, zum Beispiel ein `StringIO` Objekt als Quelle oder Ziel anstelle einer Datei auf der Festplatte.

Und bei der Prozentausgabe würde man "GUI" Code mit Funktionalität vermischen, das heisst die Funktion wäre an eine bestimmte GUI, in diesem Fall Textausgabe, fest gekoppelt. Wenn die Ausgabe ausserhalb der Funktion stattfindet, dann kannst Du Dir aussuchen wie die Prozentausgabe dargestellt wird, zum Beispiel auch als Fortschrittsbalken in einer GUI.

Zur Fehlerbehandlung: Die beiden ``finally`` Blöcke sorgen dafür, dass die Dateien auf jeden Fall geschlossen werden. Und der umschliessende ``except`` Block meldet jeden `IOError` der innerhalb des Blocks auftritt.

Die ``finally`` Blöcke wird man in Python 2.5 mit der ``with`` Anweisung etwas schöner und kompakter schreiben können.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Zum Thema "percentage", ist vielleicht http://www.python-forum.de/topic-3140.html interessant :)

btw. irgendwie find ich das spannend:

Code: Alles auswählen

source = r"\\.\C:"

f = file(source, "rb")
print f.read(1024)
f.close()
So kann man ja einfach mal umsehen :) Könnte man einen Hex-HDD-Editor bauen... Oder vielleicht besser nur ein Viewer...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten