Colton Colton - 1 month ago 39
Python Question

TypeError: encoding without a string argument

I looked up lots of similar question, but sadly none of them are close to mine.

I have a simple script that checks balance from exchange. It is a part of an unofficial API wrapper written in python and my understanding is it stuck somewhere between python 2 and python 3. I fixed errors one by one, but I'm completely stuck with this one. Here is the code:

import urllib.parse
import urllib.request
import json
import time
import hmac,hashlib


class Poloniex():
def __init__(self, APIKey, Secret):
self.APIKey = APIKey
self.Secret = Secret

def api_query(self, command, req={}):
self.req = bytes(req, 'utf-8')
req['command'] = command
req['nonce'] = int(time.time()*1000)
post_data = urllib.parse.quote(req)
my_key = self.Secret
my_key_bytes = bytes(my_key, 'utf-8')
post_data_bytes = bytes(post_data, 'utf-8')

sign = hmac.new(my_key_bytes, post_data_bytes, hashlib.sha512).hexdigest()
headers = {
'Sign': sign,
'Key': my_key_bytes,
#'Content-Type': 'application/json'
}

ret = urllib.request.urlopen(
urllib.parse.quote('https://poloniex.com/tradingApi', safe=':/'), post_data_bytes,
headers)
jsonRet = json.loads(ret.read())
return self.post_process(jsonRet)

def returnBalances(self):
return self.api_query('returnBalances')



inst = Poloniex("AAA-BBB", "123abcdef")

balance = inst.returnBalances()
print(balance)


Looks like I have a problem with syntax, but even after RTM I can't figure this out. It throws me:

TypeError: encoding without a string argument


and before that I had:

TypeError: quote_from_bytes() expected bytes


which was 'fixed' by

self.req = bytes(req, 'utf-8')


Can anybody please point me in the right direction?

Thank you.

UPD

sorry, forgot the traceback

Traceback (most recent call last):
File "script.py", line 43, in <module>
balance = inst.returnBalances()
File "script.py", line 37, in returnBalances
return self.api_query('returnBalances')
File "script.py", line 18, in api_query
post_data = urllib.parse.quote(req)
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 775, in quote
return quote_from_bytes(string, safe)
File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 800, in quote_from_bytes
raise TypeError("quote_from_bytes() expected bytes")
TypeError: quote_from_bytes() expected bytes

Answer Source

In your code, req is a dictionary, but you're attempting to convert it to bytes here: self.req = bytes(req, 'utf-8'), which doesn't make sense since only strings can be converted this way.

The second error is caused by the fact that urllib.parse.quote works only with strings and bytes, but you're passing it a dictionary.