0

私はmakeを実行してpythonプロジェクトでCライブラリをコンパイルし、自動化部分にpython(python 3.3) pexpectを使用しています。そのため、make コマンドの出力は pexpect によってチャンクで読み取られ、そのようなチャンクの 1 つで、pexpect が (python 3 バイト) を (python3 の str) type に変換しようとすると、次のエラーがスローされます。主な問題は、この問題が断続的に頻繁に発生しないことです。

UnicodeDecodeError: 'utf-8' コーデックは位置 1998-1999 のバイトをデコードできません: 予期しないデータの終わり

--> 以下のサンプル コードは、データにマルチバイト文字 (つまり、特殊文字または任意の Unicode データ) が含まれている場合を示しています。マルチバイト文字の部分データを処理している場合、Pexpect はデコードに失敗します。

#!/usr/bin/python 
# -*- coding: utf-8 -*-
from base import pexpect

MAX_READ_CHUNK = 8

def run(cmd):
    child = pexpect.spawn(cmd, maxread=MAX_READ_CHUNK)
    while True:
       i = child.expect([pexpect.EOF,pexpect.TIMEOUT])

       if child.before:
          print(child.before)

       if i == 0: # EOF
           break
       elif i == 1: # TIMEOUT
           continue

    child.close()
    return child.exitstatus

############## Main ################
data='“HELLO WORLD”' 
#i.e. data = b'\xe2\x80\x9cabcd\xe2\x80\x9d'
print("Data in readable form = %s "%data)
print("Data in bytes         = %s \n\n"%data.encode('utf-8'))

run("echo %s"%data)

次のトレースバック エラーが発生します。

Data in readable form = “HELLO WORLD” 
Data in bytes         = b'\xe2\x80\x9cHELLO WORLD\xe2\x80\x9d' 


_cast_unicode() enc=[utf-8] s=[b'\xe2\x80\x9cHELLO'] 
_cast_unicode() enc=[utf-8] s=[b' WORLD\xe2\x80'] 
Traceback (most recent call last):
  File "test.py", line 33, in <module>
    run("echo %s"%data)
  File "test.py", line 11, in run
    i = child.expect([pexpect.EOF,pexpect.TIMEOUT])
  File "/home/test/Downloads/base/pexpect.py", line 1358, in expect
    return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
  File "/home/test/Downloads/base/pexpect.py", line 1372, in expect_list
    return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
  File "/home/test/Downloads/base/pexpect.py", line 1425, in expect_loop
    c = self.read_nonblocking (self.maxread, timeout)
  File "/home/test/Downloads/base/pexpect.py", line 1631, in read_nonblocking
    return super(spawn, self).read_nonblocking(size=size, timeout=timeout)\
  File "/home/test/Downloads/base/pexpect.py", line 868, in read_nonblocking
    s2 = self._cast_buffer_type(s)
  File "/home/test/Downloads/base/pexpect.py", line 1614, in _cast_buffer_type
    return _cast_unicode(s, self.encoding)
  File "/home/test/Downloads/base/pexpect.py", line 156, in _cast_unicode
    return s.decode(enc)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 6-7:
 unexpected end of data

上記のコードで MAX_READ_CHUNK の値を 9 に変更すると、正常に動作しています。

# Output When "MAX_READ_CHUNK = 9"
Data in readable form = “HELLO WORLD” 
Data in bytes         = b'\xe2\x80\x9cHELLO WORLD\xe2\x80\x9d' 


_cast_unicode() enc=[utf-8] s=[b'\xe2\x80\x9cHELLO '] 
_cast_unicode() enc=[utf-8] s=[b'WORLD\xe2\x80\x9d\r'] 
_cast_unicode() enc=[utf-8] s=[b'\n'] 
“HELLO WORLD”

この "UnicodeDecodeError: 'utf-8' codec can't decode bytes in position: unexpected end of data" を make 中に pexpect で処理する方法。

4

1 に答える 1

0

何が起こっているかというと、pexpect が、異なるバッファーにまたがる Unicode コード ポイントのバイトの処理に失敗するということです。あなたの例では、チャンクサイズが8の倍数の場合、バイトが欠落している\xe2\x80\x9dため、デコードできません。\x9d

残念ながら、私はこれを解決する方法を知るために pexpect に精通していませんが、次の 2 つの方法を想像できます。

  • maxread1 (バッファなし) に設定してみるか、または
  • (これはダーティです) 例外をキャッチし、出力をバッファリングして、次の出力ウィンドウと共に処理します。
  • 既知のサイズのバッファーを処理している場合はmaxread、バッファー サイズに設定します。
于 2013-09-13T13:05:25.700 に答える