私は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 で処理する方法。