Friday, October 12, 2018

Python 3: TypeError: 'bytes' object does not support item assignment

Symptom:

    There is a function in the python code

mesg = { 'clientid':'eeeeeee','token':'ttttttt','channelid':'hhhhh','text':'' }
def mesg2slack(mesgtext):
    """
    send notification mesg to slack channel
    """
    global mesg
    mesg['text'] = mesgtext
    mesg = urllib.parse.urlencode(mesg).encode("utf-8")
    slackurl = 'https://test.test.com/apex/test/v1/push.message'
    req = urllib.request.Request(slackurl, data=mesg) # this will make the method "POST"
    resp = urllib.request.urlopen(req)

First invoke mesg2slack('first try '), it works fine
Second invoke mesg2slack('2nd try'), it error out with error : TypeError: 'bytes' object does not support item assignment


Diagonisis :

      Be careful when we use global variable in python. We use "global mesg"  in the function, it was set as dict type.  However when we do " mesg = urllib.parse.urlencode(mesg).encode("utf-8")  " , it changes the mesg type to be bytes. 
type(mesg)  was 'dict'  when mesg = { 'clientid':'eeeeeee','token':'ttttttt','channelid':'hhhhh','text':'' }
type(mesg)  was 'bytes' after mesg = urllib.parse.urlencode(mesg).encode("utf-8")

Solution:

    Use local variable mesgutf for urllib

def mesg2slack(mesgtext):
    """
    send notification mesg to slack channel
    """
    global mesg
    mesg['text'] = mesgtext
    mesgutf = urllib.parse.urlencode(mesg).encode("utf-8")
    slackurl = 'https://test.test.com/apex/smi/v1/push.message'
    req = urllib.request.Request(slackurl, data=mesgutf) # this will make the method "POST"
    resp = urllib.request.urlopen(req)

No comments: