4

私はgrowisofsを使用して、Pythonアプリケーションを介してisoを書き込みます。2つの異なるファイルに2つのクラスがあります。GUI()(main.py)およびBoxblaze()(core.py)。GUI()はウィンドウを構築し、すべてのイベントなどを処理します。Boxblaze()には、GUI()が呼び出すすべてのメソッドがあります。

これで、ユーザーが書き込みに使用するデバイスと書き込み先のファイルを選択したら、次のコマンドを呼び出すメソッドを呼び出す必要があります。`

growisofs -use-the-force-luke=dao -use-the-force-luke=break:1913760 -dvd-compat -speed=2 -Z /burner/device=/full/path/to.iso

このコマンドは、次のような出力を提供するはずです。

Executing 'builtin_dd if=/home/nevon/games/Xbox 360 isos/The Godfather 2/alls-tgod2.iso of=/dev/scd0 obs=32k seek=0'
/dev/scd0: "Current Write Speed" is 2.5x1352KBps.
#more of the lines below, indicating progress.
7798128640/7835492352 (99.5%) @3.8x, remaining 0:06 RBU 100.0% UBU  99.8%
7815495680/7835492352 (99.7%) @3.8x, remaining 0:03 RBU  59.7% UBU  99.8%
7832862720/7835492352 (100.0%) @3.8x, remaining 0:00 RBU   7.9% UBU  99.8%
builtin_dd: 3825936*2KB out @ average 3.9x1352KBps
/dev/burner: flushing cache
/dev/burner: closing track
/dev/burner: closing disc

このコマンドは、Boxblaze()のburn()というメソッドで実行されます。単純に次のようになります。

def burn(self, file, device):
    subprocess.call(["growisofs", '-dry-run', "-use-the-force-luke=dao", "-use-the-force-luke=break:1913760", "-dvd-compat", "-speed=2", "-Z",  device +'='+ file])

今私の質問は次のとおりです。

  1. 出力(括弧内のパーセンテージ)から進行状況を取得し、進行状況バーをその進行状況を「追跡」するように設定するにはどうすればよいですか?私のプログレスバーは、GUI()クラスで次のように呼び出されます。

    get = builder.get_object

    self.progress_window = get( "progressWindow")

    self.progressbar = get( "progressbar")

  2. GUIの応答性を維持するために、このコマンドを別のスレッドで実行する必要がありますか(プログレスバーを更新し、ユーザーが必要に応じて書き込みをキャンセルできるようにするため)?もしそうなら、どうすればそれを行うことができ、それでも進行状況を進行状況バーに渡すことができますか?


興味があれば、Launchpadで完全なコードを入手できます。バザーをインストールしている場合は、次を実行するだけです。

bzr branch lp:boxblaze

ああ、そしてあなたが不思議に思っているのであれば、このアプリケーションはLinuxでのみ動作することを意図しているので、クロスプラットフォームの互換性について心配する必要はありません。

4

4 に答える 4

3

glib.io_add_watch()サブプロセス オブジェクトの stdout および stderr に接続されたパイプの出力を監視するために使用できます。

proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_id = glib.io_add_watch(proc.stdout, glib.IO_IN|glib.IO_HUP, stdout_cb)
stderr_id = glib.io_add_watch(proc.stderr, glib.IO_IN|glib.IO_HUP, stderr_cb)

次に、コールバックが呼び出されると、状態をチェックし、パイプからすべてのデータを読み取り、それを処理して、ProgressBar を更新するための情報を取得します。アプリが io をバッファリングする場合、一度に 1 行ずつ出力するように、pty を使用して端末に接続されていると思わせる必要がある場合があります。

于 2009-09-28T01:28:08.540 に答える
1

subprocess.Popen出力を取得するには、呼び出しを使用する必要があります。(stdout = subprocess.PIPE

(2番目の質問)

GUIフレームワークが通常のループでファイル記述子を選択できない限り、おそらく別のスレッドが必要です。

バックグラウンドスレッドにパイプを読み取らせ、それを処理して(進行状況を抽出するために)、それをGUIスレッドに渡すことができます。

## You might have to redirect stderr instead/as well
proc = sucprocess.Popen(command,stdout=subprocess.PIPE)
for line in proc.stdout.readlines():
    ## might not work - not sure about reading lines
    ## Parse the line to extract progress
    ## Pass progress to GUI thread

編集:

たくさんのCDをテストして無駄にしたくないので、実行していませんが、コメントでは、情報をstdoutではなくstderrに出力しているように見えます。

サンプルコマンドをコマンドラインで直接実行し、stdoutとstderrを別のファイルにリダイレクトすることをお勧めします。

growisofs [options] >stdout 2>stderr

次に、stdoutでどのようなものが出てくるのか、stderrでどのようなものが出てくるのかを判断できます。

必要なものがstderrにある場合は、に変更stdout=subprocess.PIPEしてstderr=subprocess.PIPE、それがさらにうまく機能するかどうかを確認してください。

Edit2:

スレッドを正しく使用していません-スレッドを開始する必要があります-直接実行していません。

また:

gtk.gdk.threads_init()
threading.Thread.__init__(self)

非常に奇妙です-イニシャライザーの呼び出しはイニシャライザーにあるはずです-そして私はあなたがそれをgtkスレッドにする必要はないと思いますか?

run()メソッドを呼び出す方法は、それ自体が奇妙です。

core.Burning.run(self.burning, self.filechooser.get_filename(), self.listofdevices[self.combobox.get_active()])

オブジェクトを介してインスタンスメソッドを呼び出します。

self.burning.run(self.filechooser.get_filename(), self.listofdevices[self.combobox.get_active()])

(しかし、あなたは__init__()方法を持っているべきです)

歩く前に走ろうとしているようです。いくつかの単純なスレッデッドコード、次にgrowisofsを実行して出力を解析するためのいくつかの単純なコード、次にいくつかの単純なgtk + backgroundスレッドコードを記述してから、それらをすべて組み合わせてみてください。実際、最初にメソッドとオブジェクトを理解できるように、最初にいくつかの単純なオブジェクト指向コードを書き始めます。

たとえば、Pythonで作成するすべてのクラスは新しいスタイルのクラスである必要があり、イニシャライザーからスーパークラスのイニシャライザーを呼び出す必要があります。

于 2009-08-16T12:37:23.423 に答える
0

サブプロセスからの読み取りにタイムアウトを渡すことはできますか?私のsubProcessモジュールがその設計入力として使用されたので、できると思います。これを使用してgrowiso.read(.1)を作成し、outdata(またはerrdata)からのパーセンテージを解析して表示できます。

于 2009-08-16T12:38:47.090 に答える
0

別のスレッドからコマンドを実行し、gobject.idle_add 呼び出しで GUI を更新する必要があります。現在、「Burning」クラスがありますが、間違って使用しています。次のように使用する必要があります。

self.burning = core.Burning(self.filechooser.get_filename(), self.listofdevices[self.combobox.get_active()], self.progressbar)
self.burning.start()

明らかに、core.Burning を変更する必要があります。次に、プログレスバーにアクセスできるようになるため、次のような関数を作成できます。

def set_progress_bar_fraction(self, fraction): 
    self.progress_bar.set_fraction(fraction)

次に、パーセンテージの更新ごとに次のように呼び出します。gobject.idle_add(self.set_progress_bar_fraction, fraction)

スレッドを使用した pygtk の詳細については、こちらを参照してください。

于 2009-08-24T04:44:34.703 に答える