Python MySQLdb - Connection in a class - python

I am making a Python project where I have to seek and retreive data from a database.
I tried making a class, in which I declare the connection and do my queries, here is moreless what I have so far.
import MySQLdb
dbc =("localhost","root","1234","users")
class sql:
db = MySQLdb.connect(dbc[0],dbc[1],dbc[2],dbc[3])
cursor = db.cursor()
def query(self,sql):
sql.cursor.execute(sql)
return sql.cursor.fetchone()
def rows(self):
return sql.cursor.rowcount
sqlI = sql()
print(sqlI.query("SELECT `current_points` FROM `users` WHERE `nick` = 'username';"))
So, the main problem is that the variable db and cursor are not callable from other def's/functions from the same Class. What I'd like to get, is a polished query, where I can make queries and retreive it's content. This would summarize my code, therefore I should do.

I usually use psycopg2 / postgres, but this is the basic DB class that I often use, with Python's SQLite as an example:
import sqlite3
class Database:
def __init__(self, name):
self._conn = sqlite3.connect(name)
self._cursor = self._conn.cursor()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
#property
def connection(self):
return self._conn
#property
def cursor(self):
return self._cursor
def commit(self):
self.connection.commit()
def close(self, commit=True):
if commit:
self.commit()
self.connection.close()
def execute(self, sql, params=None):
self.cursor.execute(sql, params or ())
def fetchall(self):
return self.cursor.fetchall()
def fetchone(self):
return self.cursor.fetchone()
def query(self, sql, params=None):
self.cursor.execute(sql, params or ())
return self.fetchall()
This will let you use the Database class either normally like db = Database('db_file.sqlite) or in a with statement:
with Database('db_file.sqlite') as db:
# do stuff
and the connection will automatically commit and close when the with statement exits.
Then, you can encapsulate specific queries that you do often in methods and make them easy to access. For example, if you're dealing with transaction records, you could have a method to get them by date:
def transactions_by_date(self, date):
sql = "SELECT * FROM transactions WHERE transaction_date = ?"
return self.query(sql, (date,))
Here's some sample code where we create a table, add some data, and then read it back out:
with Database('my_db.sqlite') as db:
db.execute('CREATE TABLE comments(pkey INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR, comment_body VARCHAR, date_posted TIMESTAMP)')
db.execute('INSERT INTO comments (username, comment_body, date_posted) VALUES (?, ?, current_date)', ('tom', 'this is a comment'))
comments = db.query('SELECT * FROM comments')
print(comments)
I hope this helps!

That's not how you write classes in Python. You need to define your connection and cursor inside the __init__ method, and refer to them via self.
class sql:
dbc = ("localhost","root","1234","users")
def __init__(self):
db = MySQLdb.connect(*self.dbc)
self.cursor = db.cursor()
def query(self,sql):
self.cursor.execute(sql)
return self.cursor.fetchone()
def rows(self):
return self.cursor.rowcount

You can use constructor for the connection. When the object of class will created the constructor will invoke automatically.
import MySQLdb
class Connection:
def __init__(self):
self.con=MySQLdb.connect("127.0.0.1","root","","db_name",3306)
self.cmd=self.con.cursor()
obj=Connection()

from config import Config
import MySQLdb
class Connection:
def __init__(self):
self.db=MySQLdb.connect(
Config.DATABASE_CONFIG['server'],
Config.DATABASE_CONFIG['user'],
Config.DATABASE_CONFIG['password'],
Config.DATABASE_CONFIG['name']
)
self.db.autocommit(True)
self.db.set_character_set('utf8mb4')
self.cur=self.db.cursor()
EXAMPLE CONFIG CLASS(config.py):
class Config(object):
DATABASE_CONFIG = {
'server': 'localhost',
'user': 'dbuser',
'password': 'password',
'name': 'dbname',
}

Related

How to pass args into a class to create instance of Python Singleton pattern wrapper for PyODBC?

Looking for examples of class patterns people use to wrap PyODBC, I found this example here at SO: single database connection throughout the python application.
I don't understand how the DBConnection class works in the original example. How is DBConnector being initialized if--
cls.connection = DBConnector().create_connection()
--doesn't pass the required init values to DBConnector()? When I try to add them I get TypeError: DBConnection() takes no arguments
import pyodbc
class DBConnector(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(DBConnector, cls).__new__(cls)
return cls.instance
def __init__(self, ipaddress, port, dsn, remotedsn):
self.ipaddress = ipaddress
self.port = port
self.dsn = dsn
self.remotedsn = remotedsn
self.dsnstr_default = 'OpenMode=F;OLE DB Services=-2;'
self.dbconn = None
# creates new connection
def create_connection(self):
return pyodbc.connect(self.dsnstr_default,
IPAddress = self.ipaddress,
Port = self.port,
DSN = self.dsn,
RemoteDSN = self.remotedsn,
autocommit=True)
# For explicitly opening database connection
def __enter__(self):
self.dbconn = self.create_connection()
return self.dbconn
def __exit__(self):
self.dbconn.close()
class DBConnection(object):
connection = None
#classmethod
def get_connection(cls, new=False, *args, **kwargs): << ADDED THIS
if new or not cls.connection:
cls.connection = DBConnector(*args, **kwargs).create_connection()
/\/\/\/\/\/\/\/\/\/SEE NOTE
return cls.connection
#classmethod
def GetCompanyInfo(cls):
"""execute query on singleton db connection"""
connection = cls.get_connection()
try:
connection.setencoding('utf-8')
cursor = connection.cursor()
except pyodbc.ProgrammingError:
connection = cls.get_connection(new=True)
cursor = connection.cursor()
# Start Query
cursor.execute("SELECT CompanyName, EIN, SSN FROM Company")
for cname, ein, ssn in cursor.fetchall():
result = (cname, ein, ssn)
# End Query
cursor.close()
return result
Did some homework...
I can find several examples explaining the Singleton class pattern, so I've got the Connector class to work:
a = DBConnector('127.0.0.1', '4500', 'pyauto_local', None)
a.create_connection()
# <pyodbc.Connection at 0x5772110>
a = DBConnector('127.0.0.1', '4500', 'pyauto_local', None)
a.__enter__()
# <pyodbc.Connection at 0x605f278>
a.__exit__()
I did some testing...
I had a successful test manually inserting the connection parameters into the get_connection method:
cls.connection = DBConnector('127.0.0.1', '4500', 'pyauto_local', None).create_connection()
/\/\/\/\/\/\/ NOTED ABOVE
# Testing
cx = DBConnection()
cx.GetCompanyInfo()
# ('Zep', '12-3456789', None)
Now I'm curious
I could be done if I put the connection and queries all in the one class--Monster class.
OR I understand the Car > Blue Car OOP pattern better, and in another post here at SO is an example of extending the Singleton class. This makes more sense to me.
NOW I'm really curious how the original was supposed to work:
#classmethod
def get_connection(cls, new=False):
"""Creates return new Singleton database connection"""
if new or not cls.connection:
cls.connection = DBConnector().create_connection()
return cls.connection
How to get the parameters into DBConnection class without INIT? The post is also tagged with Django, so they may have skipped an assumed Django context? Or Django gives it for free somehow?

Where to store the DB connection for a classmethod/staticmethod

I have something similar to the following:
class InferredProvider(object):
def __init__(self):
from ingest.parse_utils import DB
db = DB()
self.conn = db.conn
self.cursor = db.cursor
#classmethod
def update_all(cls):
x = InferredProvider()
conn = x.conn
cursor = x.cursor
for item in ... [etc]
Initializing the DB seems fine for an instance...but doing it for a classmethod to update_all items seems a bit odd. What would be the suggested way to do this here?

Question: Howto change a funtion to a class in python

I want to create a class with methods, so that I do not have to create multiple functions.
Below is my code, I want to get a class with two methods. Method 1: SQL Query, method 2: sql insert.
Any tipp is greatly appreciated.
Stefan
def dbconnect():
dbconn = pymysql.connect(host='192.168.1.2', port=3307, user='username', passwd='password', db='dbname')
try:
cur = dbconn.cursor()
sqlQuery = "select * from data"
sqlQuerygetlast = "SELECT * FROM data ORDER BY id DESC LIMIT 1"
sqlQuerygetlast10 = "SELECT * FROM data ORDER BY id DESC LIMIT 10"
cur.execute(sqlQuerygetlast10)
rows = cur.fetchall()
for row in rows:
print(row)
except Exception as e:
print("Exeception occured:{}".format(e))
finally:
#dbconn.commit()
dbconn.close()
My objective is to call the methods from my code, i.e. query a select statement.
Thanks a lot
Stefan
I guess you mean that you don't want to create multiple connections?
Then you should implement it as a Context manager:
class DB:
def __init__(self):
self.dbconn = None
def get_last(self, n)
try:
cur = self.dbconn.cursor()
sqlQuerygetlast = "SELECT * FROM data ORDER BY id DESC LIMIT {}".format(n)
cur.execute(sqlQuerygetlast)
rows = cur.fetchall()
for row in rows:
print(row)
except Exception as e:
print("Exeception occured:{}".format(e))
finally:
# self.dbconn.commit()
def some_other_method(self):
self.dbconn.do_something()
def __enter__(self):
self.dbconn = pymysql.connect(
host='192.168.1.2',
port=3307,
user='username',
passwd='password',
db='dbname'
)
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
dbconn.close()
return True
and use it as follows:
with DB() as db:
db.get_last(1)
db.get_last(10)
db.some_other_method()
This will create only one instance of a database connection and close after it is finished.
Writing a class in Python is fairly simple.
Here's an example of how to write the classic Person class and how to use properties and methods.
Specifically, the presentation method is also making use of the name property.
From this example you can move on and build your Database class implementation quite easily:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def presentation(self):
print("Hello my name is " + self.name)
p1 = Person("John", 36)
p1.presentation()
Remember that in all the methods of a class you will have to specify the reserved keyword self as parameter (plus, clearly, any other parameter you might need).

Connection and Cursor inside a class in psycopg2

I would like to use the connection and cursor classes inside a custom made class. I would also like to inherit all the methods associated with the connection and cursor classes. I have done some research on it and found docs and this question related to my problem. I have some code that is working partly. i.e I can insert and update the database. However, I cannot select from the database because doing so returns none even when the row is in the database. Here is my code
from datetime import datetime, timedelta
import psycopg2
import psycopg2.extensions
class DataBase():
"""A class used to create tables in the database. Inherits from
psycopg2.extensions.connection in order to gain access to the cursor,
commit, close, and many other features from the pyscopg module.
"""
def __init__(self):
self.my_connection = psycopg2.connect(database="public", user="public",
password="general", host="127.0.0.1",
port="5432")
self.my_cursor = self.my_connection.cursor()
def query_database(self, sql_statement, *args):
return self.my_cursor.execute(sql_statement, *args)
def commit_query(self):
return self.my_connection.commit()
def fetch_one(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchone()
def fetch_all(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchall()
def __del__(self):
self.my_cursor.close()
self.my_connection.close()
############################################################################
class CreateTables(DataBase):
def create_user_table(self):
"""Helper function used to create the user_table"""
sql_statement = '''CREATE TABLE IF NOT EXISTS USERS
(ID SERIAL PRIMARY KEY,
FIRSTNAME TEXT NOT NULL,
LASTNAME TEXT NOT NULL,
USERNAME TEXT NOT NULL UNIQUE,
EMAIL TEXT NOT NULL UNIQUE,
PASSWORD TEXT NOT NULL,
DATETIMEREGISTERED TIMESTAMP NOT NULL);'''
user_table = DataBase.query_database(self, sql_statement)
DataBase.commit_query(self)
return user_table
def create_entries_table(self):
"""Helper function used to create an entries table."""
sql_statement = '''CREATE TABLE IF NOT EXISTS ENTRIES
(ID SERIAL PRIMARY KEY,
TITLE TEXT NOT NULL,
DRINK TEXT NOT NULL,
DATEOFORDER TIMESTAMP NOT NULL,
TIMETODELIVERY TIMESTAMP NOT NULL,
SETREMINDER TIMESTAMP NOT NULL,
USERID INT REFERENCES USERS ON DELETE CASCADE);'''
entries_table = DataBase.query_database(self, sql_statement)
DataBase.commit_query(self)
print("entries table created.")
return entries_table
# test = CreateTables() This is working well
# print(test.create_entries_table())
#####################################################################
class OperateDatabase(CreateTables):
def create_user(self, email, username, *args):
"""Helper function used to create a user"""
sql_statement = """SELECT ID FROM USERS WHERE EMAIL = %s OR
USERNAME = %s;"""
user_in_database = CreateTables.fetch_one(self, sql_statement,
(email, username,))
print("the user in database is :>>", user_in_database)
sql_statement2 = """INSERT INTO USERS (FIRSTNAME, LASTNAME, USERNAME,
EMAIL, PASSWORD, DATETIMEREGISTERED)
VALUES (%s, %s, %s, %s, %s, %s);"""
if not user_in_database:
CreateTables.query_database(self,sql_statement2, *args)
CreateTables.commit_query(self)
return True
return False
data = ("Jkdai", "Jkdal", "Jkdai", "jkdai#gmail.com", "password", datetime.now())
test = OperateDatabase()
print(test.create_user("jkdai#gmail.com", "jkdai", data))
#Inserts the user the very first time implying the insert statement is working
#raises an integrity error the second time implying the select statement is not working.
#Also the print statement defaults to false when it is supposed to return the user's id.
cursor.execute() returns a vendor-defined value (it's not specified in the db-api spec), and for pyscopg2 it is actually documented as returning None indeed, so this:
def query_database(self, sql_statement, *args):
return self.my_cursor.execute(sql_statement, *args)
def fetch_one(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchone()
will obviously not work as you expect. You could return self.my_cursor() from query_database() instead, ie:
def query_database(self, sql_statement, *args):
self.my_cursor.execute(sql_statement, *args)
return self.my_cursor
def fetch_one(self, sql_statement, *args):
cursor = self.query_database(sql_statement, *args)
return cursor.fetchone()
but there's a fundamental flaw with this code, which is that it's not reentrant (nor thread safe FWIW). Actually, your class should NOT store a cursor as part of it's state and reuse it over and over (db-api cursors are not meant to be used that way) but create a new cursor for every operation (which is the indented use).
Also, you should not rely on __del__(self) to close your connection. The __del__() method is not a proper C++/Java style finalizer and is not even garanteed to be called when the object is collected. Actually, trying to wrap a db connection and cursor in a class is usually not a good idea, at least not this way.

Insert in sqlite python doesn't change table

I'm create simple class for SQLite datadase and when I'm insert new row table doesn't change.
DB.py
import sqlite3
class DB:
def __init__(self, **kwargs):
self.db = sqlite3.connect('passwods.db')
self.c = self.db.cursor()
self.c.execute('CREATE TABLE IF NOT EXISTS passwords (name, value)')
def insert(self, alias, cipher):
column = (alias, cipher)
self.c.execute('INSERT INTO passwords (name, value) VALUES (?,?)', column)
self.db.commit()
def get(self, alias):
pk = (alias,)
self.c.execute('SELECT * FROM passwords WHERE name=?', pk)
def getAll(self):
self.c.execute('SELECT * FROM passwords')
Interactive shell
>>> from DB import DB
>>> db = DB()
>>> db.insert('firstName', 'firstValue')
>>> print(db.getAll())
None
>>>
Your method getAll has no return statement. If you add it, you can see that the table actually changes:
def getAll(self):
self.c.execute("SELECT * FROM passwords")
return self.c.fetchall()

Categories