프로그래밍/Python

[python] TypeError: argument 'data': 'memoryview' object cannot be converted to 'PyBytes'

채윤아빠 2024. 6. 19. 10:43
728x90
반응형

문제점 및 증상

다음과 같이 "fastcrc"를 이용한 간단한 CRC 계산 코드를 작성하였습니다.
10 바이트를 그냥 던져서 계산하는 것과, 5바이트씩 나누어 계산한 결과가 같은지 확인하는 예시입니다.

메모리 뷰를 이용한 것은 대량 메모리에 대한 CRC 계산을 위하여, 전체 메모리를 복사하지 않도록 하기 위해서 였습니다.

from fastcrc import crc16

data = b'1234567890'

crc = crc16.kermit(data)
print(f'crc16 (1) = {crc:04X}')

mv_data = memoryview(data)
temp_crc = 0
temp_crc = crc16.kermit(mv_data[0:5]), temp_crc)
temp_crc = crc16.kermit(mv_data[5:], temp_crc)

print(f'crc16 (2) = {temp_crc:04X}')


위 코드를 실행하면 아래와 같이 "TypeError: argument 'data': 'memoryview' object cannot be converted to 'PyBytes'" 오류가 발생합니다.

Traceback (most recent call last):
  File "D:\Dev\demo\crc16-kermit.py", line 15, in 
    temp_crc16 = crc16.kermit(mv_data[0:5], temp_crc16)
  File "c:\Dev\Python\Python310\lib\site-packages\fastcrc\crc16.py", line 352, in kermit
    return _crc_16_kermit(data, initial)
    return _crc_16_kermit(data, initial)
TypeError: argument 'data': 'memoryview' object cannot be converted to 'PyBytes'

해결 방안

tobytes() 메소드 이용

가장 손쉬운 방법은 tobytes() 메소드를 이용하는 것입니다. 명확하고 직관적이며 가장 안전한 방법입니다.

from fastcrc import crc16

data = b'1234567890'

crc = crc16.kermit(data)
print(f'crc16 (1) = {crc:04X}')

mv_data = memoryview(data)
temp_crc = 0
temp_crc = crc16.kermit(mv_data[0:5].tobytes(), temp_crc)
temp_crc = crc16.kermit(mv_data[5:].tobytes(), temp_crc)

print(f'crc16 (2) = {temp_crc:04X}')


실행한 결과는 다음과 같습니다.

crc16 (1) = 286B
crc16 (2) = 286B

bytes() 함수 이용

from fastcrc import crc16

data = b'1234567890'

crc = crc16.kermit(data)
print(f'crc16 (1) = {crc:04X}')

mv_data = memoryview(data)
temp_crc = 0
temp_crc = crc16.kermit(bytes(mv_data[0:5]), temp_crc)
temp_crc = crc16.kermit(bytes(mv_data[5:]), temp_crc)

print(f'crc16 (2) = {temp_crc:04X}')

결언

아쉽게도 fastcrc 패키지의 함수들이 memoryview를 지원하지 않았습니다.
memoryview를 이용하는 것보 bytes를 직접 나누어(slice) 계산하는 것이 보다 효율적입니다.

from fastcrc import crc16

data = b'1234567890'

crc = crc16.kermit(data)
print(f'crc16 (1) = {crc:04X}')

temp_crc = 0
temp_crc = crc16.kermit(data[0:5], temp_crc)
temp_crc = crc16.kermit(data[5:], temp_crc)

print(f'crc16 (2) = {temp_crc:04X}')


대용량의 메모리를 처리하거나, 큰 파일을 처리할 경우에는 두 번째 블록별로 CRC를 계산하여 추가하는 방법을 잘 활용해야 겠습니다.