2016/11/23

[py]1バイト分のstrを数値に変換するならord()が使える

先頭にデータ長が付いたstr型のデータを扱うことが多い。
こんなのだ。

cmd = '\x03\x12\x34\x56'

Cだったら、先頭のデータ長を取ってきたい場合、こうするだろう。

cmd = "\x03\x12\x34\x56";
uint8_t length = (uint8_t)cmd[0];

pythonだと、いつもこうやっている。

cmd = '\x03\x12\x34\x56'
length = struct.unpack('B', cmd[0])[0]

 

これが、ぱっと頭に思いつかない。。
そして、長い。
他に方法はないのだろうか?


1つ私が勘違いしていたのは、16進数でデータを突っ込んだ文字列はbytearray型だと思い込んでいたことだ。
文字列は、文字列だ。だからstr型になる。

これがッ、bytearray型だッ!

cmd = bytearray([0x03, 0x12, 0x34, 0x56])

まあ、他に記述方法があるのかもしれんが、見つけたのがこの書き方だった。
Cの書き方に近い。

この書き方の利点は、数値を取ってくることが可能なところだ。

cmd = bytearray([0x03, 0x12, 0x34, 0x56])
print 'cmd[0]=', cmd[0]

期待通り!

ただ、str型ではないので、こういうのはできない。

print 'cmd=', cmd.encode('hex')

が、これならいける。

print 'cmd=', str(cmd).encode('hex')

 

そうか。。。SQLiteで取ってきたBLOB型をstrして使っていたが、こういう意味だったのか・・・。
そういえば、BLOB型にINSERTとかするときも、bytearrayで囲んでいるし。

 

今はstrベースでやっているので、こういう感じで使うのがよさそうだ。

cmd = '\x03\x12\x34\x56'
print 'cmd=', cmd.encode('hex')
length = bytearray(cmd)[0]
cmd_byte = cmd[1: 1 + length]
print 'cmd_byte=', cmd_byte.encode('hex')

これだと、3バイト分表示されるので、これでいこう。

lengthに代入するのが「bytearray(cmd[0])」だとダメだった。
1バイト分取ってくるという意味では同じそうに見えるのだが。。。


などとごにょごにょ調べていたら、もう1つ別の方法を見つけた。
ord()だ。

length = ord(cmd[0])

こういうのを求めてたんだよ!

 

逆のパターンの、数値を文字列化する場合はchr()だそうだ。
今までこうやって書いていたのだけど、

%02x' % length

これでよいことになる(lengthの範囲によるけど)。

chr(length)

こう書くと、「cmd2= 02789a」となる。

cmd2 = chr(2) + chr(0x78) + chr(0x9a)
print 'cmd2=', cmd2.encode('hex')

 

組み込み関数は、私が求めているものが多そうなので気に掛けておかねば。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。