0

I have a class with two variables set to some default value. I have defined a function where I declare these variables as global inside my function. I get this error which says the variable is not defined. One variable is counter, which will increment on each function call and other variable has to append message on each call. After appending multiple messages and counter value reaches some threshold I want to insert all these messages into MySQL database. But the variable is not appending the values. It shows the variable is undefined.

class Message():
     insertStatement= ''
     insertCounter = 0

    def Save(self, msg)
        global insertCounter
        global insertStatement 

        if  msg.topic.startswith("topic1/"):
            insertStatement += "INSERT INTO mydatabase.table VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
       elif msg.topic.startswith("topic2/"):
            insertStatement += "INSERT INTO mydatabase.table1 VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
       elif msg.topic.startswith("topic3/")   
            insertStatement += "INSERT INTO mydatabase.table2 VALUES (" +msg.payload.decode("utf-8") + "," + datetime + ");"
       elif msg.topic.startswith("messages"):
            insertStatement += "INSERT INTO mydatabase.table3 VALUES ('" + msg.topic + "',"  + msg.payload.decode("utf-8") + "," + datetime + ");"
       else:
            return  
       insertcounter +=1
       if(insertCounter > 1000):
         for result in cursor.execute(insertStatement, multi=True):
             print result.row_count  # i changed it to result
5
  • please include the actual error msg Commented Dec 8, 2017 at 11:02
  • 1
    A healthy mix of global and string formatting of SQL statements... Why do you need to define these as global rather than attributes? Commented Dec 8, 2017 at 11:03
  • Also, you can only execute one statement at a time. So even if your giant string was constructed correctly, it would throw an error. Commented Dec 8, 2017 at 11:08
  • "reslut.row_count" xD Commented Dec 8, 2017 at 11:19
  • Please try to read your code again and identify simple errors, before posting here. You can use pylint for identify your errors in your python code. Commented Dec 8, 2017 at 11:41

4 Answers 4

1

You probably only need instance variables:

class Message():
    def __init__(self):
        self.insertStatement= ''
        self.insertCounter = 0

    def Save(self, msg)
        if msg.topic.startswith("topic1/"):
            self.insertStatement += "INSERT INTO mydatabase.table VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
        elif msg.topic.startswith("topic2/"):
            self.insertStatement += "INSERT INTO mydatabase.table1 VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
        elif msg.topic.startswith("topic3/")   
            self.insertStatement += "INSERT INTO mydatabase.table2 VALUES (" +msg.payload.decode("utf-8") + "," + datetime + ");"
        elif msg.topic.startswith("messages"):
            self.insertStatement += "INSERT INTO mydatabase.table3 VALUES ('" + msg.topic + "',"  + msg.payload.decode("utf-8") + "," + datetime + ");"
        else:
            return  
        self.insertcounter += 1
        if self.insertCounter > 1000:
            # do the SQL thing

As a programmer you should try very, very, very hard to not use global variables.

Sign up to request clarification or add additional context in comments.

4 Comments

On the SQL side, there's two major issues with this. First, string formatting leaves them wide open to SQL injection attacks. Second, I'm almost positive that MySQL will not allow multiple INSERT statements in a single string. The OP should execute each statement as it arises and then commit() once their counter hits 1000.
@roganjosh: Yes, that's up to the OP. If I can correct the global/instance thing, then maybe these things will become apparent.
@roganjosh Thanks for the suggestions. Using this API dev.mysql.com/doc/connector-python/en/… ,If multi is set to True, execute() is able to execute multiple statements specified in the operation string. So, I tried to insert multiple statements. My intention is to buffer the messages until it reaches threshold and do bulk insert.
@user1731770 I did not know that. However, note that a strong suggestion of mine is to use parameterized statements to avoid SQL Injection, and the documentation says "However, using parameters does not work well in this case, and it is usually a good idea to execute each statement on its own."
1

Please check the last line. It should be result instead of reslut.

Comments

1

There are couple of typos in your code, please update that and check.

  1. You have declared a global variable insertCounter and incrementing variable insertcounter. Update it to self.insertCounter+1
  2. Update your result variable, it suppose to be result, not reslut

Comments

1

The variables insertStatement and insertCounter are class variables. You dont have to reference them as global inside Save(). To access these class variables use Message.insertStatement and Message.insertCounter

 class Message():
         insertStatement= ''
         insertCounter = 0

        def Save(self, msg):

            if  msg.topic.startswith("topic1/"):
                Message.insertStatement += "INSERT INTO mydatabase.table VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
           elif msg.topic.startswith("topic2/"):
                Message.insertStatement += "INSERT INTO mydatabase.table1 VALUES (" + msg.payload.decode("utf-8") + "," + datetime + ");"
           elif msg.topic.startswith("topic3/")   
                Message.insertStatement += "INSERT INTO mydatabase.table2 VALUES (" +msg.payload.decode("utf-8") + "," + datetime + ");"
           elif msg.topic.startswith("messages"):
                Message.insertStatement += "INSERT INTO mydatabase.table3 VALUES ('" + msg.topic + "',"  + msg.payload.decode("utf-8") + "," + datetime + ");"
           else:
                return  
           Message.insertcounter +=1
           if(Message.insertCounter > 1000):
             for result in cursor.execute(Message.insertStatement, multi=True):
                 print result.row_count  # i changed it to result

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.