在代码中兼容地使用字符串和类字节对象在 Python 2 和 Python 2 中运行3 [英] Using strings and byte-like objects compatibly in code to run in both Python 2 & 3

查看:42
本文介绍了在代码中兼容地使用字符串和类字节对象在 Python 2 和 Python 2 中运行3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试修改下面显示的代码,该代码在 Python 2.7.x 中有效,因此它在 Python 3.x 中也可以保持不变.但是,我遇到了以下问题,我无法在第一个函数 bin_to_float() 中解决,如下面的输出所示:

I'm trying to modify the code shown far below, which works in Python 2.7.x, so it will also work unchanged in Python 3.x. However I'm encountering the following problem I can't solve in the first function, bin_to_float() as shown by the output below:

float_to_bin(0.000000): '0'
Traceback (most recent call last):
  File "binary-to-a-float-number.py", line 36, in <module>
    float = bin_to_float(binary)
  File "binary-to-a-float-number.py", line 9, in bin_to_float
    return struct.unpack('>d', bf)[0]
TypeError: a bytes-like object is required, not 'str'

我试图通过在调用 struct.unpack() 之前添加一个 bf = bytes(bf) 来解决这个问题,但这样做产生了它自己的 类型错误:

I tried to fix that by adding a bf = bytes(bf) right before the call to struct.unpack(), but doing so produced its own TypeError:

TypeError: string argument without an encoding

所以我的问题是有可能解决这个问题并实现我的目标吗?如果是这样,如何?最好是在两种版本的 Python 中都可以使用的方式.

So my questions are is it possible to fix this issue and achieve my goal? And if so, how? Preferably in a way that would work in both versions of Python.

以下是适用于 Python 2 的代码:

Here's the code that works in Python 2:

import struct

def bin_to_float(b):
    """ Convert binary string to a float. """
    bf = int_to_bytes(int(b, 2), 8)  # 8 bytes needed for IEEE 754 binary64
    return struct.unpack('>d', bf)[0]

def int_to_bytes(n, minlen=0):  # helper function
    """ Int/long to byte string. """
    nbits = n.bit_length() + (1 if n < 0 else 0)  # plus one for any sign bit
    nbytes = (nbits+7) // 8  # number of whole bytes
    bytes = []
    for _ in range(nbytes):
        bytes.append(chr(n & 0xff))
        n >>= 8
    if minlen > 0 and len(bytes) < minlen:  # zero pad?
        bytes.extend((minlen-len(bytes)) * '0')
    return ''.join(reversed(bytes))  # high bytes at beginning

# tests

def float_to_bin(f):
    """ Convert a float into a binary string. """
    ba = struct.pack('>d', f)
    ba = bytearray(ba)
    s = ''.join('{:08b}'.format(b) for b in ba)
    s = s.lstrip('0')  # strip leading zeros
    return s if s else '0'  # but leave at least one

for f in 0.0, 1.0, -14.0, 12.546, 3.141593:
    binary = float_to_bin(f)
    print('float_to_bin(%f): %r' % (f, binary))
    float = bin_to_float(binary)
    print('bin_to_float(%r): %f' % (binary, float))
    print('')

推荐答案

我的方法与 @metatoaster 的答案不同.我只是修改了 int_to_bytes 以使用并返回一个 bytearray:

I had a different approach from @metatoaster's answer. I just modified int_to_bytes to use and return a bytearray:

def int_to_bytes(n, minlen=0):  # helper function
    """ Int/long to byte string. """
    nbits = n.bit_length() + (1 if n < 0 else 0)  # plus one for any sign bit
    nbytes = (nbits+7) // 8  # number of whole bytes
    b = bytearray()
    for _ in range(nbytes):
        b.append(n & 0xff)
        n >>= 8
    if minlen > 0 and len(b) < minlen:  # zero pad?
        b.extend([0] * (minlen-len(b)))
    return bytearray(reversed(b))  # high bytes at beginning

这似乎在 Python 2.7.11 和 Python 3.5.1 下无需任何其他修改即可工作.

This seems to work without any other modifications under both Python 2.7.11 and Python 3.5.1.

请注意,我用 0 而不是 '0' 进行零填充.我没有做太多测试,但这肯定是你的意思吗?

Note that I zero padded with 0 instead of '0'. I didn't do much testing, but surely that's what you meant?

这篇关于在代码中兼容地使用字符串和类字节对象在 Python 2 和 Python 2 中运行3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆