コードを書く前に、1 つお勧めしたいことがあります。「ビットフィールド」の値は、バイトに分割できる長さではありません。ビット文字列を扱うときはいつでも、バイトのサイズで大きくすることをお勧めします (例 if len(bitfield)%8 != 0: print 'ビットフィールドを完全にバイトで表現できることを確認してください!')。さまざまなプログラミング言語、プログラミング言語内のさまざまなライブラリ、およびさまざまなデータベースでのフィールドの操作方法にあいまいさがないことを確認してください。つまり、データベース、Python、私が推奨するライブラリなどはすべて、このビット配列をバイト配列の形式で格納または表現できるようになります。提供された bitarray がバイトに均等に分割されない場合、次の 3 つのいずれかが発生します。1) エラーが発生します。(これは楽観的です) 2) ビット配列は自動的に左にパディングされます。3) bitarray は自動的に右側にパディングされます。
ある種のビット文字列ライブラリを使用することをお勧めします。この目的のためにpython-bitstringを使用しました。ここでは ODBC を扱うのに時間はかかりませんでしたが、考え方は基本的に同じで、srgerg の回答を活用しています。
例:
#!/usr/bin/python
import pymssql
from binascii import hexlify
from bitstring import BitArray
dbconninfo = {'host': 'hostname', 'user': 'username', 'password': 'secret', 'database': 'bitexample', 'as_dict': True}
conn = pymssql.connect(**dbconninfo)
cursor = conn.cursor()
bitfield = "000001110100111000110101100010"
ba = BitArray(bin=bitfield)
print '%32d (bitfield -> BitArray -> int)' % ba.int
cursor.execute("CREATE TABLE bin_test (bin_col varbinary(max) )")
cursor.execute("INSERT INTO bin_test values (%s)", (ba.int,))
cursor.execute("SELECT bin_col FROM bin_test")
results = cursor.fetchone()['bin_col'] # results now contains binary packed data '\x01\xd3\x8db'
conn.rollback()
results_int = int(hexlify(results),16)
print '%32d (bitfield -> BitArray -> int -> DB (where data is binary packed) -> unpacked with hexlify -> int)' % results_int
print '%32s (Original bitfield)' % bitfield
from_db_using_ba_hexlify_and_int_with_length = BitArray(int=int(hexlify(results),16), length=30).bin
print '%32s (From DB, decoded with hexlify, using int to instantiate BitArray, specifying length of int as 30 bits, out as bin)' %
from_db_using_ba_hexlify_and_int_with_length
from_db_using_ba_hex = BitArray(hex=hexlify(results)).bin # Can't specify length with hex
print '%32s (From DB, decoded with hexlify, using hex to instantiate BitArray, can not specify length, out as bin)' % from_db_using_ba_hex
from_db_using_ba_bytes_no_length = BitArray(bytes=results).bin # Can specify length with bytes... that's next.
print '%32s (From DB, using bytes to instantiate BitArray, no length specified, out as bin)' % from_db_using_ba_bytes_no_length
from_db_using_ba_bytes = BitArray(bytes=results,length=30).bin
print '%32s (From DB, using bytes to instantiate BitArray, specifying length of bytes as 30 bits, out as bin)' % from_db_using_ba_bytes
from_db_using_hexlify_bin = bin(int(hexlify(results),16))
print '%32s (from DB, decoded with hexlify -> int -> bin)' % from_db_using_hexlify_bin
from_db_using_hexlify_bin_ba = BitArray(bin=bin(int(hexlify(results),16))).bin
print '%32s (from DB, decoded with hexlify -> int -> bin -> BitArray instantiated with bin)' % from_db_using_hexlify_bin
from_db_using_bin = bin(int(results,16))
print '%32s (from DB, no decoding done, using bin)' % from_db_using_bin
これの出力は次のとおりです。
30641506 (bitfield -> BitArray -> int)
30641506 (bitfield -> BitArray -> int -> DB (where data is binary packed) -> unpacked with hexlify -> int)
000001110100111000110101100010 (Original bitfield)
000001110100111000110101100010 (From DB, decoded with hexlify, using int to instantiate BitArray, specifying length of int as 30 bits, out as bin)
00000001110100111000110101100010 (From DB, decoded with hexlify, using hex to instantiate BitArray, can not specify length, out as bin)
00000001110100111000110101100010 (From DB, using bytes to instantiate BitArray, no length specified, out as bin)
000000011101001110001101011000 (From DB, using bytes to instantiate BitArray, specifying length of bytes as 30 bits, out as bin)
0b1110100111000110101100010 (from DB, decoded with hexlify -> int -> bin)
0b1110100111000110101100010 (from DB, decoded with hexlify -> int -> bin -> BitArray instantiated with bin)
Traceback (most recent call last):
File "./bitexample.py", line 38, in <module>
from_db_using_bin = bin(int(results,16))
ValueError: invalid literal for int() with base 16: '\x01\xd3\x8db'
バイトに直接分割できるビット文字列 (30 ビットを表す文字列) がないため、まったく同じ文字列を取得する唯一の方法は長さを指定することであり、それでも結果は得られなかったことに注意してください。 BitArray がどのようにインスタンス化されたかによって異なります。