0

I am trying to create a global variable in python, but it seems that I don't understand well the concept. I have created a my_connection vairable in a module called mysql_example and then I have initialized it inside the MysqlExample class, but after that, the value is cleared. My mysql_example module have the following code:

import datetime
import mysql.connector as mysql

my_connection = None


class MysqlExample(object):

    def __init__(self, config : dict ):
        my_connection = mysql.Connect( **config )
        my_connection.autocommit = True
    
    def close(self):
        self._endExtraction()
        my_connection.close()
    
    def __enter__(self):
        self._id_extraction = self._startExtraction()
        return self
        
    def __exit__(self, type, value, tb ):
        self.close()
    
    def _startExtraction(self):
        cur = my_connection.cursor()
        cur.execute( '''select * from simple_test''' )
        return cur.lastrowid
        
    def _endExtraction(self):
        self._lock.acquire()
        cur = my_connection.cursor()
        cur.execute('''select * from simple_test''', 
            { 'id_extraction' : self._id_extraction, 
              'end_date' : datetime.datetime.now() } )
        self._lock.release()
        

and the main call is like this:

with MysqlExample({ "host" : "XXXX", 
                              "database" : "XXXXX",
                              "user" : "XXXXX", 
                              "password" : "super-secret-password" }) as my_example: 
    print("hello")

The error the code shows is:

AttributeError: 'NoneType' object has no attribute 'cursor'

And that is because the value my_connection is re-initialized in apparently every method call. Is that the usual behaviour in python???

Yevhen Kuzmovych
  • 10,940
  • 7
  • 28
  • 48
Raul Luna
  • 1,945
  • 1
  • 17
  • 26
  • You are missing the global keyword in any function that utilises "myconnection" https://www.w3schools.com/python/python_variables_global.asp – tomgalpin Feb 20 '23 at 12:29
  • When you do `my_connection = mysql.Connect( **config )` in the `__init__`, all it does is create a new ***local*** variable to that method. What you probably wanted is `self.my_connection = ...` and then all other methods to reference that `self.my_connection` – Tomerikoo Feb 20 '23 at 13:15

2 Answers2

1

You need to use the Global keyword to inform the __init__ function that my_connection belongs to the global namespace

def __init__(self, config : dict ):
    global my_connection
    my_connection = mysql.Connect( **config )
    my_connection.autocommit = True
Yevhen Kuzmovych
  • 10,940
  • 7
  • 28
  • 48
tomgalpin
  • 1,943
  • 1
  • 4
  • 12
  • 3
    Honestly, it looks more like OP wants `my_connection` to be an instance variable... – AKX Feb 20 '23 at 12:34
  • Yes i agree, the code could be better organised and better optimised. My answer is to purely address the reason to why the error occurs, considering the opening remark is "I am trying to create a global variable". – tomgalpin Feb 20 '23 at 12:37
  • Yes, @AKX, it should be an instance variable. I am trying to do some stuff in multithreading, but the class I am developing closes the connection and I do not why. So I was trying to move the connection to a global variable when I got this error. That I should already know, by the way – Raul Luna Feb 20 '23 at 12:41
0

You do not want to do that. You have to choose what kind of variable my_connection is and then stick to that choice. It can be:

  • an instance variable. It is only declared and used inside objects of the class, and each object has its own connection. Init/close should look like:

      class MysqlExample(object):
          def __init__(self, config : dict ):
              self.my_connection = mysql.Connect( **config )
              self.my_connection.autocommit = True
    
          def close(self):
              self._endExtraction()
              self.my_connection.close()
    
  • a global variable. It should be declared, initialized and closed outside of any object. Of course you are responsable for initializing it before any attempt to use it, and close it when done.

      def init_connection(config : dict ):
          global my_connection
          my_connection = mysql.Connect( **config )
          my_connection.autocommit = True
    
      def close_connection(self):
          my_connection.close()
    
      class MysqlExample(object):
          ...
    

Your current code mixed both ways. That means that every new object will create a new global my_connection object (and leak the previous one), but the first object to die will close the global connection. Definitely a wrong design...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252