2016/11/28

[py3]2to3ではdecode/encode('hex')などは変換してくれないようだ

さて、いま作っているプロジェクトもpython3対応しようと、2to3.pyにかけてみた。
ワイルドカードで指定できなかったので、cygwinでxargsを使ったが、printがprint()になっているので変換できたのだろう。
よし、とpyCharmの設定もpython3にして開いてみると、指摘がたくさん。。。

こんなのが指摘されている。

struct.pack('<H', length).encode('hex')

bytes = lenstr.decode('hex')

 

hiro99ma blog: [py]python3は16進数の扱いが違うんだ

違うんだ、を実感した瞬間である。


decode/encodeはstr型用だから、bytes型だと使えない。
struct.pack()はbytes型で返すようになっている。
だから、bytes型の扱いに変換すればよいだけのことだ。

文字.decode('hex')は、bytes.fromhex(文字)にすればよいはずだ。
そこはそれで済みそうだが、"\xab\x12"のようにして作っていた文字列をbytes型に変換しないと、fromhex()したデータとの足し算というか連結ができないことがわかった。
これは、文字列の前に「b」を付けるだけでよいようだ。

と、やってみたのだが、bytesの要素をord()したりstruct.unpack()すると怒られる。。。

ord(cmd_bytes[0])

strがほしいのにintが渡されている、ということだった。
デバッガで見てみると、bytes配列の要素はint型になっていた。
そうか、ord()しなくてもいいんだ。。。

が、これはこれで別の問題が起きた。
辞書のkeyとして"\xab"のような値を使っていたのだが、これをbytes型にしないと検索できなくなった。
しかし、検索するのはbytesから1バイト取ってきたデータなので、そのままだとint型になってしまう。
よくわからんので、cmd_bytes[0].to_bytes(1, byteorder='little')、などとしてbytes型に変換して、動きはしたのだけど、ダサい。。。

4. 組み込み型 — Python 3.5.2 ドキュメント
なるほど、要素として取り出すとintになるから、サイズ1の配列として取り出せばよいのか。

cmd = cmd_bytes[pos: pos+1]

こんなのでよい。
数値にしたければ、cmd[0]とすればよいだけなので、こっちの方が扱いやすいな。

 

encode('hex')するのは目で読める文字にするとき、decode('hex')するのは実際のデータにするとき、という使い分けをしていた。
これは、bytes型にhex()というメソッドがあり、それでよかった。


私がbytes型を使うときのやり方をまとめると、こう。

  • 文字列でエスケープシーケンスを使って16進数を表していた→あたまに「b」を付ける
  • decode('hex')していた→bytes.fromhex()にする
  • ord()していた→bytesを1要素として取り出す(data[3]など)
  • bytes型として切り出したい→配列として取り出す(data[3:4]など)
  • encode('hex')していた→hex()にする

struct.pack/unpack()は、to_bytes()もあるし、あまり使わないかも。
to_bytes()の逆はなさそうだから、unpack()は使うことになるか。。。あ、int.from_bytes()というのもあるようだ。
to_bytes()はメソッドなのに、from_bytes()はstaticメソッドなのはなんでだろう?

 

pyCharmで指摘が出ているのは、あからさまにbytes型になったと分かる箇所だけだ。
型指定がないから、引数でもらったものをdecode('hex')などとしていても、そこは出てない。
だから、たくさん指摘が出ていると思ったけど、氷山の一角なのだ。
2to3でやってくれよーと思ったのだが、これはちょっと無理だな。

 

また、変換しようとしていたpythonプロジェクトは、str型のbytearrayで扱う場合と、str型で16進数文字列を扱う場合が混在していて、あっちではstruct.pack/unpack、こっちではdecode/encode('hex')と、実にまとまりがない。

今回は、python3にするのだったら、もう一度書き直した方が早そうだ。。。

0 件のコメント:

コメントを投稿

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