I'm just curious here, but I have been using bytes() to convert things to bytes ever since I learned python. It was until recently that I saw struct.pack(). I didn't bother learning how to use it because I thought It did essentially did the same thing as bytes(). But it appears many people prefer to use struct.pack(). Why? what are the advantages of one over the other?
bytes() does literally what the name implies:

Return a new “bytes” object, which is an immutable sequence of
  integers in the range 0 <= x < 256

struck.pack() does something very different:

This module performs conversions between Python values and C structs represented as Python strings

While for some inputs these might be equivalent, they are not at all the same operation. struct.pack() is essentially producing a byte-string that represents a POD C-struct in memory. It's useful for serializing/deserializing data.
Python-bytes() vs struct.pack()