1

Pythonを使用して、RaspberryPiでCFカードをイメージングするためのツールを作成しようとしています。

で圧縮画像を実装するまで、ほとんどの機能が動作していましたdd

gzipの出力をパイプしようとすると、プロセスddを突いてdd進行状況を取得することができなくなります。

複数のサブプロセスを使用しようとしましたが、パイプが壊れたり、そのようなファイルエラーが発生しません。

以下は私のコードです:

#!/usr/bin/env python
from Adafruit_CharLCD import Adafruit_CharLCD
import os
import sys
import time
import signal
from subprocess import Popen, PIPE
lcd = Adafruit_CharLCD()
lcd.begin(16,2)
imgpth = '/home/pi/image/image_V11.img.gz'
line0 = ""
line1 = ""
q = 0
r = 0
s = 0

def lcdPrint(column, row, message, clear=False):
    if ( clear == True ):
        lcd.clear()

    lcd.setCursor(column, row)
    lcd.message(message)

lcd.clear()                 
lcdPrint(0, 0, 'Preparing Copy', True)
lcdPrint(0, 1, '')

gz = Popen(['gunzip -c /home/pi/image/image_V11.img.gz'], stdout=PIPE)
dd = Popen(['dd of=/dev/sda'],stdin=gz.stdout, stderr=PIPE)                     

filebyte = os.path.getsize(imgpth)                                  
flsz = filebyte/1024000 

while dd.poll() is None:                                        
    time.sleep(1)
    dd.send_signal(signal.SIGUSR1)
    while 1:                                            
        l = dd.stderr.readline()
    if '(' in l:                                            
        param, value = l.split('b',1)                           
        line1 = param.rstrip()                              
        r = float(line1)                                    
        s = r/1024000
        break
lcdPrint(0, 0, 'Copying....', True)
q = round(s/flsz*100, 2)                                
per = str(q)        

lcdPrint(0, 1, per + '% Complete',)

lcdPrint(0, 0, 'Copy Complete', True)   
time.sleep(1)
exit()

どうすればこれを修正できますか?

4

1 に答える 1

0

私はまったく同じことをしているので、この質問に出くわしました。私の完全な解決策はここにあります:

私が持っているものとあなたのものとの違いをいくつか選んでみました。

dd を開始するときに、stderr と stdout の両方をパイプにリダイレクトしました。

dd = subprocess.Popen(['dd', 'of=/dev/sda', 'bs=1M'], bufsize=1, stdin=unzip.stdout, stdout=PIPE, stderr=STDOUT)

これは本当に違いを生むべきではないと思います。必要なものはすべて stderr に移動する必要がありますが、何らかの理由で混乱しているように見えました。

別のスレッドを使用して、dd からの出力を取得します。

def read_pipe(out, queue):
    for line in iter(out.readline, b''):
        queue.put(str(line))
    out.close()

dd_queue = queue.Queue()
dd_thread = threading.Thread(target = read_pipe, args=(dd.stdout, dd_queue))
dd_thread.daemon = True
dd_thread.start()

次に、電話すると:

dd.send_signal(signal.SIGUSR1)

出力は dd_queue でキャッチされます。

また、gzip 圧縮されたファイルの非圧縮サイズが最後の 4 バイトに格納されていることもわかりました。

fl = open(str(imgpath), 'rb')
fl.seek(-4, 2)
r = fl.read()
fl.close()
size = struct.unpack('<I', r)[0]

os.path.getsize(imgpth) は圧縮されたサイズのみを提供するため、パーセンテージの計算は間違っています。

于 2014-01-24T22:10:36.053 に答える