Python에서 문자열을 ctypes.c_ubyte 배열로 변환하는 효율적인 방법

Askldjd

20 바이트의 문자열이 있는데 ctypes.c_ubyte비트 필드 조작을 위해 배열 로 변환하고 싶습니다 .

 import ctypes
 str_bytes = '01234567890123456789'
 byte_arr = bytearray(str_bytes)
 raw_bytes = (ctypes.c_ubyte*20)(*(byte_arr))

캐스트를 위해 str에서 bytearray 로의 깊은 복사를 피하는 방법이 있습니까?

또는 딥 카피없이 문자열을 바이트 배열로 변환 할 수 있습니까? (memoryview와 같은 기술로?)

Python 2.7을 사용하고 있습니다.

성능 결과 :

eryksunBrian Larsen 의 제안을 사용하여 Ubuntu 12.04 및 Python 2.7을 사용하는 vbox VM의 벤치 마크는 다음과 같습니다.

  • method1은 내 원래 게시물을 사용합니다.
  • method2는 ctype from_buffer_copy를 사용합니다.
  • method3은 ctype 캐스트 / POINTER를 사용합니다.
  • method4는 numpy를 사용합니다.

결과 :

  • method1은 3.87 초 소요
  • method2는 0.42 초 소요
  • method3은 1.44 초 소요
  • method4는 8.79 초 소요

암호:

import ctypes
import time
import numpy

str_bytes = '01234567890123456789'

def method1():
    result = ''
    t0 = time.clock()
    for x in xrange(0,1000000):     
        byte_arr = bytearray(str_bytes)
        result = (ctypes.c_ubyte*20)(*(byte_arr))

    t1 = time.clock()
    print(t1-t0)

    return result

def method2():

    result = ''
    t0 = time.clock()
    for x in xrange(0,1000000):     
        result = (ctypes.c_ubyte * 20).from_buffer_copy(str_bytes)

    t1 = time.clock()
    print(t1-t0)

    return result

def method3():

    result = ''
    t0 = time.clock()
    for x in xrange(0,1000000):     
        result = ctypes.cast(str_bytes, ctypes.POINTER(ctypes.c_ubyte * 20))[0]

    t1 = time.clock()
    print(t1-t0)

    return result

def method4():

    result = ''
    t0 = time.clock()
    for x in xrange(0,1000000):     
        arr = numpy.asarray(str_bytes)
        result = arr.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte*len(str_bytes)))

    t1 = time.clock()
    print(t1-t0)

    return result

print(method1())
print(method2())
print(method3())
print(method4())
에릭 선

나는 당신이 생각하는 방식으로 작동하지 않습니다. bytearray문자열의 복사본을 만듭니다. 그런 다음 인터프리터는 bytearray시퀀스를 a로 압축을 풀고 다른 인수가있는 starargs tuple다른 새 항목에 병합합니다 tuple(이 경우에는 없음에도 불구하고). 마지막으로, c_ubyte배열 이니셜 라이저 배열 tuple의 요소를 설정하기 위해 args 반복 합니다 c_ubyte. 배열을 초기화하기 위해서는 많은 작업과 복사 작업이 필요합니다.

대신 from_buffer_copy문자열이 버퍼 인터페이스 (유니 코드 아님)가있는 바이트 문자열이라고 가정 하여 메서드 를 사용할 수 있습니다 .

import ctypes    
str_bytes = '01234567890123456789'
raw_bytes = (ctypes.c_ubyte * 20).from_buffer_copy(str_bytes)

여전히 문자열을 복사해야하지만 한 번만 수행되고 훨씬 더 효율적입니다. 주석에서 언급했듯이 Python 문자열은 변경할 수 없으며 인턴 또는 사전 키로 사용할 수 있습니다. ctypes가 실제로 이것을 위반하도록 허용하더라도 불변성은 존중되어야합니다.

>>> from ctypes import *
>>> s = '01234567890123456789'
>>> b = cast(s, POINTER(c_ubyte * 20))[0]
>>> b[0] = 97
>>> s
'a1234567890123456789'

편집하다

불변의 CPython 문자열을 수정하기 위해 ctypes를 사용하는 것을 권장하지 않는다는 점을 강조해야합니다. 필요한 경우 최소한 sys.getrefcount참조 횟수가 2 이하인지 미리 확인하십시오 (호출에 1이 추가됨). 그렇지 않으면 결국 이름 (예 :) "sys"및 코드 객체 상수에 대한 문자열 인터 닝에 놀라게 될 것 입니다. 파이썬은 적절하다고 생각되는대로 변경 불가능한 객체를 자유롭게 재사용 할 수 있습니다. '불변'개체를 변경하기 위해 언어를 벗어나면 계약이 깨졌습니다.

예를 들어 이미 해시 된 문자열을 수정하면 캐시 된 해시가 더 이상 내용에 맞지 않습니다. 그것은 dict 키로 사용하기 위해 그것을 깨뜨립니다. 새 내용이있는 다른 문자열이나 원래 내용이있는 문자열은 dict의 키와 일치하지 않습니다. 전자는 다른 해시를 가지며 후자는 다른 값을 갖습니다. 그런 다음 dict 항목을 얻는 유일한 방법은 잘못된 해시가있는 변경된 문자열을 사용하는 것입니다. 이전 예에서 계속 :

>>> s
'a1234567890123456789'
>>> d = {s: 1}
>>> d[s]
1

>>> d['a1234567890123456789']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'a1234567890123456789'

>>> d['01234567890123456789']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '01234567890123456789'

이제 열쇠가 수십 곳에서 재사용되는 인턴 문자열이라면 혼란을 고려하십시오.


성능 분석을 위해 timeit 모듈을 사용하는 것이 일반적입니다. 3.3 이전 버전 timeit.default_timer은 플랫폼에 따라 다릅니다. POSIX 시스템 time.time에서는이고 Windows에서는 time.clock.

import timeit

setup = r'''
import ctypes, numpy
str_bytes = '01234567890123456789'
arr_t = ctypes.c_ubyte * 20
'''

methods = [
  'arr_t(*bytearray(str_bytes))',
  'arr_t.from_buffer_copy(str_bytes)',
  'ctypes.cast(str_bytes, ctypes.POINTER(arr_t))[0]',
  'numpy.asarray(str_bytes).ctypes.data_as('
      'ctypes.POINTER(arr_t))[0]',
]

test = lambda m: min(timeit.repeat(m, setup))

>>> tabs = [test(m) for m in methods]
>>> trel = [t / tabs[0] for t in tabs]
>>> trel
[1.0, 0.060573711879182784, 0.261847116395079, 1.5389279092185282]

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

바이트 배열을 분할 한 다음 Python에서 문자열로 변환하는 효율적인 방법

분류에서Dev

문자열을 c_ubyte 배열로 C에 전달

분류에서Dev

int를 c에 문자열로 저장하는 효율적인 방법

분류에서Dev

C에서 부호없는 문자 배열을 빼는 가장 효율적인 방법

분류에서Dev

C ++에서 숫자 값을 문자 배열에 효율적으로 다시 할당하는 방법

분류에서Dev

C ++의 문자열에서 구두점을 제거하는 가장 효율적인 방법

분류에서Dev

문자열을 배열로 분할하는 효율적인 방법-PHP

분류에서Dev

Java에서 문자열을 대체하는 메모리 효율적인 방법

분류에서Dev

C #에서 문자열 배열 값을 개체로 변환하는 방법

분류에서Dev

Array <Dictionary <String, String >>에서 문자열의 배열을 추출하는 효율적인 방법

분류에서Dev

Swift3에서 1 차원 배열을 2 차원 배열로 효율적으로 변환하는 방법

분류에서Dev

Bigendian 형식으로 QByteArray에서 float 배열을 얻는 효율적인 방법

분류에서Dev

쉼표로 구분 된 문자열을 C에서 문자열 배열로 변환하는 방법

분류에서Dev

PHP에서 문자열의 하위 문자열을 추출하는 가장 효율적인 방법

분류에서Dev

JSON을 구문 분석하고 Python에서 CSV로 변환하는보다 효율적인 방법

분류에서Dev

Java에서 이진 문자열을 이진 바이트 배열로 효율적으로 변환하는 방법은 무엇입니까?

분류에서Dev

unsigned / signed integer / long을 우아하고 효율적인 방법으로 C 문자열로 변환하는 방법은 무엇입니까?

분류에서Dev

효율적인 방법으로 C에서 배열 크기를 결정하기위한 제안 필요

분류에서Dev

Python에서 2D 배열을 채우는 효율적인 방법

분류에서Dev

JavaScript에서 문자열을 배열로 변환하는 방법

분류에서Dev

mongodb에서 배열을 문자열로 변환하는 방법

분류에서Dev

Twig에서 문자열을 배열로 변환하는 방법

분류에서Dev

Julia에서 3D 배열을 2D 배열로 변환하는 가장 효율적인 방법은 무엇입니까?

분류에서Dev

Numpy 배열에서 열을 삭제하는 효율적인 방법?

분류에서Dev

Python : 대문자 앞에 문자열 앞에 공백을 추가하는 효율적인 방법

분류에서Dev

Numpy 배열에서 "다른 번호로 변경"을 구현하는 효율적인 방법

분류에서Dev

Rebol3에서 자체 인덱스로 배열을 채우는 효율적인 방법

분류에서Dev

특정 다른 하위 문자열 다음에 하위 문자열을 얻는 가장 효율적인 방법

분류에서Dev

C에서 변경 가능한 문자열을 구현하는 가장 효율적인 방법은 무엇입니까?

Related 관련 기사

  1. 1

    바이트 배열을 분할 한 다음 Python에서 문자열로 변환하는 효율적인 방법

  2. 2

    문자열을 c_ubyte 배열로 C에 전달

  3. 3

    int를 c에 문자열로 저장하는 효율적인 방법

  4. 4

    C에서 부호없는 문자 배열을 빼는 가장 효율적인 방법

  5. 5

    C ++에서 숫자 값을 문자 배열에 효율적으로 다시 할당하는 방법

  6. 6

    C ++의 문자열에서 구두점을 제거하는 가장 효율적인 방법

  7. 7

    문자열을 배열로 분할하는 효율적인 방법-PHP

  8. 8

    Java에서 문자열을 대체하는 메모리 효율적인 방법

  9. 9

    C #에서 문자열 배열 값을 개체로 변환하는 방법

  10. 10

    Array <Dictionary <String, String >>에서 문자열의 배열을 추출하는 효율적인 방법

  11. 11

    Swift3에서 1 차원 배열을 2 차원 배열로 효율적으로 변환하는 방법

  12. 12

    Bigendian 형식으로 QByteArray에서 float 배열을 얻는 효율적인 방법

  13. 13

    쉼표로 구분 된 문자열을 C에서 문자열 배열로 변환하는 방법

  14. 14

    PHP에서 문자열의 하위 문자열을 추출하는 가장 효율적인 방법

  15. 15

    JSON을 구문 분석하고 Python에서 CSV로 변환하는보다 효율적인 방법

  16. 16

    Java에서 이진 문자열을 이진 바이트 배열로 효율적으로 변환하는 방법은 무엇입니까?

  17. 17

    unsigned / signed integer / long을 우아하고 효율적인 방법으로 C 문자열로 변환하는 방법은 무엇입니까?

  18. 18

    효율적인 방법으로 C에서 배열 크기를 결정하기위한 제안 필요

  19. 19

    Python에서 2D 배열을 채우는 효율적인 방법

  20. 20

    JavaScript에서 문자열을 배열로 변환하는 방법

  21. 21

    mongodb에서 배열을 문자열로 변환하는 방법

  22. 22

    Twig에서 문자열을 배열로 변환하는 방법

  23. 23

    Julia에서 3D 배열을 2D 배열로 변환하는 가장 효율적인 방법은 무엇입니까?

  24. 24

    Numpy 배열에서 열을 삭제하는 효율적인 방법?

  25. 25

    Python : 대문자 앞에 문자열 앞에 공백을 추가하는 효율적인 방법

  26. 26

    Numpy 배열에서 "다른 번호로 변경"을 구현하는 효율적인 방법

  27. 27

    Rebol3에서 자체 인덱스로 배열을 채우는 효율적인 방법

  28. 28

    특정 다른 하위 문자열 다음에 하위 문자열을 얻는 가장 효율적인 방법

  29. 29

    C에서 변경 가능한 문자열을 구현하는 가장 효율적인 방법은 무엇입니까?

뜨겁다태그

보관