This question already has answers here:
Is there a way to get a schema of a database from within python?
(10 answers)
Closed 6 years ago.
class DatabaseManager(object): ##Ignore the indentation##
def __init__(self, db):
self.conn = sqlite3.connect(db)
self.conn.execute('pragma foreign_keys = on')
self.conn.commit()
self.c = self.conn.cursor()
def query_params(self, arg, params=None):
self.c.execute(arg, params)
self.conn.commit()
return self.c
def query(self, arg):
self.c.execute(arg)
self.conn.commit()
return self.c
def fetch(self):
self.c.fetchall()
self.conn.commit()
return self.c
def __del__(self):
self.conn.close()
dbmgr = DatabaseManager("connect.db")
Other code
....
....
....
and then:
def read_from_db():
tables = []
query = "SELECT name FROM sqlite_master WHERE type='table'"
dbmgr.query(query)
rows = dbmgr.fetch()
for row in rows:
tables.append(row)
print (tables)
I am not able to figure out how to view the tables in my database, they are real as I can see them in my sqlite manager. This used to work when I did not have the class and just did:
def read_from_db():
tables = []
c.execute("SELECT name FROM sqlite_master WHERE type='table'")
rows = c.fetchall()
for row in rows:
tables.append(row)
print (tables)
So, you fetch the result, but never do anything with it, then return the spent cursor...
def fetch(self):
self.c.fetchall() # this returns a list of your data
self.conn.commit()
return self.c
It's also not clear what you are committing in the function
Compare to your other code,
rows = c.fetchall()
So you should only need
def fetch(self):
return self.c.fetchall()
Then call it
tables = dbmgr.fetch()
Or, alternatively
tables = dbmgr.query(query).fetchall()
Note that you are making an empty list, then adding elements of a list to that list. You can shortcut that process by assigning tables directly
Related
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).
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.
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()
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',
}
I'm new to Python. I've just created a sqlite3 db wrapper class to handle the database interaction in my application. My question is how do I return success/failure messages from my db wrapper class methods, addRow, updRow (which add and update rows) to the invoking program?
Here's the class code I cobbled together so far:-
class dbManager(object):
def __init__(self, db):
self.conn = lite.connect(db)
self.conn.execute('pragma foreign_keys = on')
self.conn.execute('pragma synchronous=off')
self.conn.commit()
self.cur = self.conn.cursor()
def query(self, arg):
self.cur.execute(arg)
self.conn.commit()
return self.cur
def addRow(self, tablename, data):
"""
Insert data into a table. The data does not have to be escaped.
"""
global actInserts
# Create a new cursor
# tc = self.conn.cursor() # opened at init
tablelist = ""
valueholder = ""
valuelist = []
for key, value in data.items():
if len(tablelist) > 0:
tablelist += ', '
valueholder += ', '
# Add to table column list
tablelist += key
# Add a holder
valueholder += '?'
# build the insert values
valuelist.append(value)
# Perform and commit the insert
try:
dbResponse = self.cur.execute("INSERT INTO " + tablename + " (" + tablelist + ") VALUES (" + valueholder + ");", valuelist)
actInserts += 1
except lite.Error, e:
dbResponse = 'Sqlite Error NP: ' + e.args[0]
print 'Sqlite Error NP: ' + e.args[0]
return dbResponse
def closeConnection (self):
self.conn.commit()
self.conn.close()
def __del__(self):
self.conn.close()
I think there are 2 ways you can do this. You can:
Change the return type of you function to something like a tuple of (error_code, SQL_results), or
Throw an exception if the query fails (or don't catch the one you already are handling) and leave the exception handling logic to the user (calling program).
I think option 2 is the better way.
Also, I think your query building would be more clear (or at least more concise) using something like the following (assumes that data is a dictionary)
tablelist = ','.join(list(data.viewkeys()))
valueholder = ','.join(['?' for i in data.viewkeys()])
valuelist = list(data.viewvalues())