I'm migrating some legacy python2 code to python3, and came across this function:
FRAMESTART_A = 231
FRAMETYPE_VIDEO = 6
def prepMessage(self, x):
self.nextMessage = []
bytes = []
bytes.append(FRAMESTART_A) # frame start
bytes.append(FRAMETYPE_VIDEO) # addresss
for n in range(self.width):
# set values from [0, width]
value = 65535 * \
(1.0 - (math.pow(0.5 * (math.sin(x / 2000 time.time()) 1), 4)))
bytes.append(value)
for n in range(50 - self.width):
# set bytes from [width, :] to zero
bytes.append(0)
message = apply(struct.pack,["BB" "H"*(len(bytes)-2)] bytes)
self.nextMessage.append(message)
Conceptually, I get that this is creating a byte array of items that's always 50 bytes long, with the last bytes padded to zero. In Python3, apply()
doesn't exist anymore, so the problem is with the line:
message = apply(struct.pack,["BB" "H"*(len(bytes)-2)] bytes)
Reading the docs, it looks like I can just use the *
operator to apply the function to a list of arguments, as so:
message = struct.pack(*(["BB" "H" * (len(bytes) - 2)] bytes))
But this produces a runtime error:
message = struct.pack(*(["BB" "H" * (len(bytes) - 2)] bytes))
struct.error: required argument is not an integer
Looking at the python3 struct.pack
documentation, it looks like I should get input a formatting string that looks like "BBHHHHHHH..." and then give it the byte array. However, the original code works! So I'm not sure how message = apply(struct.pack,["BB" "H"*(len(bytes)-2)] bytes)
worked, unless struct.pack
worked substantially different in python2.
What's the right way to port this forward to get working code?
CodePudding user response:
If you want to recreate apply
in Python 3, it's pretty easy:
def apply(func, args, kwargs=None):
return func(*args) if kwargs is None else func(*args, **kwargs)
If you want to make the code work on either Py2 or Py3, just put this at the top of your file to make a fallback apply
when it's not provided:
try:
apply
except NameError:
def apply(func, args, kwargs=None):
return func(*args) if kwargs is None else func(*args, **kwargs)
That said, you don't really need apply
either on Py2 or Py3; any time you see:
apply(somefunc, someargs)
like this, you can change it to just:
somefunc(*someargs)
so in this case, it would be:
message = struct.pack(*["BB" "H"*(len(bytes)-2)] bytes)
or even more simply (since concatenating one thing onto the front only to unpack immediately is unnecessary when you can just pass that one thing and unpack the rest without the extra temporary):
message = struct.pack("BB" "H"*(len(bytes)-2), *bytes)