5

I am working on converting an existing program from Python2 to Python3. One of the methods in the program authenticates the user with a remote server. It will prompt the user to enter in a password.

def _handshake(self):
    timestamp = int(time.time())
    token = (md5hash(md5hash((self.password).encode('utf-8')).hexdigest()
                + str(bytes('timestamp').encode('utf-8'))))
    auth_url = "%s/?hs=true&p=1.2&u=%s&t=%d&a=%s&c=%s" % (self.name,
                                                          self.username,
                                                          timestamp,
                                                          token,
                                                          self.client_code)
    response = urlopen(auth_url).read()
    lines = response.split("\n")
    if lines[0] != "OK":
        raise ScrobbleException("Server returned: %s" % (response,))
    self.session_id = lines[1]
    self.submit_url = lines[3]

The problem with this method is that after the integer is converted to a string, it needs to be encoded. But as far as I can tell, it is already encoded? I found this question but I was having a hard time applying that to the context of this program.

This is the line giving me problems.

  • + str(bytes('timestamp').encode('utf-8'))))
    • TypeError: string argument without an encoding

I have tried playing around with alternate ways of doing this, all with varying types of errors.

  • + str(bytes('timestamp', 'utf-8'))))
    • TypeError: Unicode-objects must be encoded before hashing
  • + str('timestamp', 'utf-8')))
    • TypeError: decoding str is not supported

I'm still getting started learning Python (but I have beginner to intermediate knowledge of Java), so I am not completely familiar with the language yet. Does anyone have any thoughts on what this issue might be?

Thanks!

Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59
J.W.F.
  • 641
  • 2
  • 12
  • 24
  • I notice the code in the link has changed that line to `+ str(timestamp)).hexdigest())` is that possibly what needs to be done? – Tadhg McDonald-Jensen Jun 02 '16 at 20:56
  • `str(bytes('timestamp').encode('utf-8'))` - what the heck? What were you trying to do there? – user2357112 Jun 02 '16 at 20:56
  • @TadhgMcDonald-Jensen Originally, it was, but when I was trying to run the script (e.g. `+ str(b'timestamp').hexdigest()))`), I received a `AttributeError: 'str' object has no attribute 'hexdigest'` in return. It might be, but I'm not quite sure on this one. – J.W.F. Jun 02 '16 at 23:32
  • @user2357112 I've been trying all kinds of combinations to get this line right, it's gone through many forms today... ultimately, I'm trying to just get this integer to convert to a format that Py3 will take as valid. – J.W.F. Jun 02 '16 at 23:33
  • do you understand that `timestamp` is a name, `'timestamp'` is a string literal (no relation to the `timestamp` name)? You don't need bytes here. To convert an integer to a string in Python: `str(timestamp)`. Use `urllib.parse.urlencode()` to create the query. Pass it `str` objects (Unicode in Python). You might need to call `.decode('ascii', 'strict')` on a `.hexdigest()` result, to get `str` instead of `bytes`. – jfs Jun 03 '16 at 00:19

1 Answers1

12

This error is due to how you create bytes in python 3.

You will not do bytes("bla bla") but just b"blabla" or you need to specify an encoding type like bytes("bla bla","utf-8") because it needs to know what was the original encoding before turning it into an array of numbers.

Then the error

TypeError: string argument without an encoding

Should disappear.

You have either bytes or str. If you have a bytes value and you want to turn it in str you should do:

my_bytes_value.decode("utf-8")

And it will return you a str.

I hoped it help ! Have a nice day !

Oekhny
  • 194
  • 8
  • Hi, thanks for the response! So, I first tried rewriting it just as `b'timestamp'`, but this gave me `TypeError: Can't convert 'bytes' object to str implicitly`. Instead, I tried doing `str(b'timestamp')`, but this outputs `TypeError: Unicode-objects must be encoded before hashing`. Your explanation makes sense, but I'm just having a hard time figuring out to return the value as a string. I tried using a `decode("utf-8")` but to no avail. Any thoughts or ideas? – J.W.F. Jun 02 '16 at 23:39
  • do `bytes('timestamp','utf-8')` – MilkyWay90 Dec 21 '18 at 02:03
  • Now I'm getting `TypeError: urlopen() got an unexpected keyword argument 'encoding'` – ScottyBlades Apr 09 '20 at 00:37