How to make a button insert data into my database? - python

I'm doing a little python product registration program and the database just doesn't open
I tried to open with sqlite3 library and by suggestion tried with QSqlDatabase, but nothing works. What could this error be? How to solve and connect?
i changed the database connection
path = r'C:\Users\Daniel\Desktop\Sistema NaruHodo\Banco de Dados'
conn = sqlite3.connect(path+r'\produtos.db')
cursor = conn.cursor()
Erro:
C:\Users\Daniel\AppData\Local\Programs\Python\Python37\pythonw.exe "C:/Users/Daniel/Desktop/Sistema NaruHodo/cadastroprodutos.py"
Process finished with exit code -1073740791 (0xC0000409)
Here is the def I'm using to try to get the field data and insert it into the database.
def addProduto(self, produtotext, estoquetext, precocustotext, precovendatext, fornecedorcomboBox):
path = r'C:\Users\Daniel\Desktop\Sistema NaruHodo\Banco de Dados'
conn = sqlite3.connect(path+r'\produtos.db')
produto = str(self.produtotext.text())
estoque = float(self.estoquetext.text())
precocusto = float(self.precocustotext.text())
precovenda = float(self.precovendatext.text())
fornecedor = str(self.fornecedorcomboBox.currentText())
conn.execute(f"""INSERT INTO produ VALUES (null, {produto}, {estoque}, {precocusto}, {precovenda}, {fornecedor})""")
conn.commit()

It looks like you're trying to display the database in a table. I recommend using a QSqlDatabase to create a connection to the database (it does support an SQLite driver). Using this instead of sqlite3 allows for better integration with the PyQt5 framework. Specifically, it can be easily hooked up with a QSqlTableModel and then displayed with a QTableView. For this approach, I suggest you familiarise yourself with model/view programming. It may seem more involved and complex than the QTableWidget you are currently using, but it's well worth it for the easy database integration it offers.
Excuse some of the doc links being for PySide2; the PyQt5 docs aren't exactly complete unfortunately.

I solved the problem, with QSqlDatabase it did not accept and gave drivers error, so I went back to sqlite3. But it was still crashing even connected, so I found that the problem was really in the function that I didn't convert to string
def addProduto(self):
self.banco = sqlite3.connect('Vendas.db')
self.cursor = banco.cursor()
Nome = self.produtotext.text()
Quant = self.estoquetext.text()
Valor = self.precocustotext.text()
Preco = self.precovendatext.text()
Forn = self.fornecedorcomboBox.currentText()
if Nome != '' or Quant != '' or Valor != '' or Preco != '' or Forn != '':
self.banco.execute(f"""INSERT INTO Produtos VALUES ('{Nome}',{Quant}, {Valor}, {Preco}, '{Forn}')""")
self.banco.commit()
self.LoadDatabase()
self.limparcampos()

Related

Using SQLite Python and Multithreading

I'm desperately trying to get this code to work from about 70 threads, where it won't be run exactly at the same time, but pretty closely. All I really want is a way of saying, try to insert this, and if you can't back off for a while and try again, just doit without breaking the database. I'm using no options when creating the database, except for the filename. The only problem is I'm getting lots of disk I/O errors and database disk image is malformed. I'm trying to run this in a transaction, so if anything goes wrong it should roll back. I've tried the isolation_level=None option on the connection, which didn't really help. I'm using the Python sqlite3 module.
Here's the code
update_simulations_end_time_sql = """update simulations set end_time=?, completion_status =? where id=?;"""
def __set_time(sql_command, data):
retries=0
while retries<5:
try:
with create_tables.create_connection() as conn:
cur = conn.cursor()
cur.execute("begin")
cur.execute(sql_command, data)
return
except Exception as e:
print(f"__set_time has failed with {sql_command}")
print(e)
sleep_time = uniform(0.1,4)
print(f"Sleeping for {sleep_time}")
sleep(sleep_time)
retries+=1
raise Exception(f"__set_time failed after {retries}")
Here's the options sqlite was compiled with
sqlite> SELECT * FROM pragma_compile_options;
COMPILER=gcc-9.4.0
ENABLE_COLUMN_METADATA
ENABLE_DBSTAT_VTAB
ENABLE_FTS3
ENABLE_FTS3_PARENTHESIS
ENABLE_FTS3_TOKENIZER
ENABLE_FTS4
ENABLE_FTS5
ENABLE_JSON1
ENABLE_LOAD_EXTENSION
ENABLE_PREUPDATE_HOOK
ENABLE_RTREE
ENABLE_SESSION
ENABLE_STMTVTAB
ENABLE_UNKNOWN_SQL_FUNCTION
ENABLE_UNLOCK_NOTIFY
ENABLE_UPDATE_DELETE_LIMIT
HAVE_ISNAN
LIKE_DOESNT_MATCH_BLOBS
MAX_SCHEMA_RETRY=25
MAX_VARIABLE_NUMBER=250000
OMIT_LOOKASIDE
SECURE_DELETE
SOUNDEX
THREADSAFE=1
USE_URI
If anyone has any ideas on how to solve this, I would be amazingly grateful.
In Python 3.11 you will be able to use the sqlite3 module with options like (link):
import sqlite3
if sqlite3.threadsafety == 3:
check_same_thread = False
else:
check_same_thread = True
conn = sqlite3.connect(":memory:", check_same_thread=check_same_thread)

Saving a variable after the python code has run to access it when code is to be run again

I am trying to retrieve data from a mysql server, run a code using the data retrieved, then push the data back to the database on different columns. I have managed to get all of that working as seen in my code attached.
However, new rows will be added constantly to the database and i don't want to have to load the entire database everytime. I want the code to only run on the new rows that have been added. Therefore, i am trying save the student_id and retrieve it somehow and the beginning of the code.
I tried different methods and i even tried pickle but i was left with little luck. The aim is to have the code run continuously on a remote server so i would really appreciate if someone can help me out as it will help me achieve my task.
Note: This is only dummy data and code but is pretty much the method of what i am trying to achieve.
import mysql.connector
import numpy as np
import time
import pickle
filename = 'saved_id'
infile = open(filename,'rb')
st_id = pickle.load(infile)
print(number)
conn = mysql.connector.connect(user="user", password='password',
host="demo.mysql.database.azure.com", port=3306)
conn.autocommit = True
cursor = conn.cursor()
cursor.execute("USE testdb;")
while True:
outfile = open(filename,'wb')
cursor.execute(f"SELECT * FROM student WHERE student_id >= {st_id};")
myresult = np.array(cursor.fetchall())
print (myresult)
for row in myresult:
mark_1 = np.random.randint(0,100)
mark_2 = np.random.randint(0,100)
mark_3 = np.random.randint(0,100)
iid = row[0]
pickle.dump(iid,outfile)
outfile.close()
cursor.execute(f"UPDATE student SET grade_1 = {mark_1}, grade_2 = {mark_2}, grade_3 = {mark_3} WHERE student_id = {iid};")
time.sleep(5)
I Think the problem is that when i initially run the code the pickle value doesn't have an input, and when i try to use a standard variable method it will not be defined which will result in some kind of error as well.
Please also do let me know if there are any aspects of my code that could be improved for speed, efficiency!

Selecting record from mySQL via cursors returns an None object

I am writing a script in python 3.x using mysqlconnector.
What I am trying to achieve right now is to check if there is a record inside my db which may be a duplicate to the one I am analyzing right now.
I came up with such code:
def fill_data(self, db_name, data):
cursor = self.cnx.cursor(buffered=True)
isDuplicate = cursor.execute(("SELECT destination FROM {0} WHERE destination = '{1}';")
.format(db_name, data['destination']))
print(cursor.statement)
self.commit()
print(isDuplicate is None)
Though I still get isDuplicate as None object. I tried to check via cursor.statement what statement is being passed to my db: it turned out that while in script I get None obj while passed in db that query works fine.
I also tried SELECT COUNT(1) FROM db_name which also gave me different results.
I am out of ideas: maybe you guys can help me out?
Update:
The solution that works for me was:
q = ("SELECT * FROM {0} WHERE destination = %s AND countryCode = %s AND prefix = %s")
.format(db_name)
cursor.execute(q, (data['destination'], data['country_code'], data['prefix']))
self.cnx.commit()
isDoubled = cursor.fetchone()
So at the end of the day it was all about fetching data from the cursor :)
Maybe the reason of your issue is the way you use execute() method.
Try to make some changes and see what is printed out:
def fill_data(self, db_name, data):
cursor = self.cnx.cursor(buffered=True)
q = 'SELECT count(*) FROM {} WHERE destination = %s'.format(db_name)
duplicate_count = cursor.execute(q, (data['destination'], )).fetchall()
print(duplicate_count)
Why should I provide query parameters this way? (article is on psql, but the core principles are the same as in mysql)
update
If you are still receiving "NoneType" object has no atribute "fetchall", then the error is probably here:
cursor = self.cnx.cursor(buffered=True)
Looks like you are not creating cursor at all. I can take a look at it if you post some code about cnx creation.

Write to MS Access table, python win32com

I'm playing around with win32com.client for python to try to write/insert a row to a MS Access table. I've found an example of how to connect and query an Access table here. Basically, their code slightly modified for my own use is:
import win32com.client
connection = win32com.client.Dispatch(r'ADODB.Connection')
DSN = 'PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=c:\\testdb.mdb;'
connection.Open(DSN)
recordset = win32com.client.Dispatch(r'ADODB.Recordset')
recordset.Open('SELECT * FROM Table1', connection, 1, 3)
fields_dict = {}
for x in range(recordset.Fields.Count):
fields_dict[x] = recordset.Fields.Item(x).Name
print fields_dict[x], recordset.Fields.Item(x).Value
So this tells me how to execute a select statement on the Access table. I'd like to be able to write rows and data to the table. When using win32com for MS Office products, I tend to dive into the MSDN pages and try to interpret the VBA code for python code, but this one has me a bit handcuffed. Couple that with no examples found on the internet after lengthy searches has made me second guess whether or not this is possible? hopefully someone out there has played with this before and has a suggestion.
As I mentioned in my comment to the question, using pyodbc (or pypyodbc) and the Access ODBC driver is a more common way of doing CRUD operations, but if you really want to use win32com and OLEDB then you could do an UPDATE like this:
import win32com.client
# ADODB constants
adVarWChar = 202
adInteger = 3
adParamInput = 1
connection = win32com.client.Dispatch(r'ADODB.Connection')
DSN = (
r'PROVIDER=Microsoft.Jet.OLEDB.4.0;'
r'DATA SOURCE=C:\Users\Public\mdbTest.mdb;'
)
connection.Open(DSN)
cmd = win32com.client.Dispatch(r'ADODB.Command')
cmd.ActiveConnection = connection
cmd.CommandText = "UPDATE Donors SET LastName = ? WHERE ID = ?"
cmd.Parameters.Append(cmd.CreateParameter("?", adVarWChar, adParamInput, 255))
cmd.Parameters.Append(cmd.CreateParameter("?", adInteger, adParamInput))
cmd.Parameters(0).Value = "Thompson"
cmd.Parameters(1).Value = 10
cmd.Execute()
connection.Close()

What should I refactor in my Python Class?

I'm fairly new to Python. And this is my first class:
import config # Ficheiro de configuracao
import twitter
import random
import sqlite3
import time
import bitly_api #https://github.com/bitly/bitly-api-python
class TwitterC:
def logToDatabase(self, tweet, timestamp):
# Will log to the database
database = sqlite3.connect('database.db') # Create a database file
cursor = database.cursor() # Create a cursor
cursor.execute("CREATE TABLE IF NOT EXISTS twitter(id_tweet INTEGER AUTO_INCREMENT PRIMARY KEY, tweet TEXT, timestamp TEXT);") # Make a table
# Assign the values for the insert into
msg_ins = tweet
timestamp_ins = timestamp
values = [msg_ins, timestamp_ins]
# Insert data into the table
cursor.execute("INSERT INTO twitter(tweet, timestamp) VALUES(?, ?)", values)
database.commit() # Save our changes
database.close() # Close the connection to the database
def shortUrl(self, url):
bit = bitly_api.Connection(config.bitly_username, config.bitly_key) # Instanciar a API
return bit.shorten(url) # Encurtar o URL
def updateTwitterStatus(self, update):
short = self.shortUrl(update["url"]) # Vou encurtar o URL
update = update["msg"] + short['url']
# Will post to twitter and print the posted text
api = twitter.Api(consumer_key=config.consumer_key,
consumer_secret=config.consumer_secret,
access_token_key=config.access_token_key,
access_token_secret=config.access_token_secret)
status = api.PostUpdate(update) # Fazer o update
msg = status.text # Vou gravar o texto enviado para a variavel 'msg'
# Vou gravar p a Base de Dados
self.logToDatabase(msg, time.time())
print msg # So p mostrar o texto enviado. Comentar esta linha de futuro.
x = TwitterC()
x.updateTwitterStatus({"url": "http://xxxx.com/?cat=49", "msg": "Searching for some ....? "})
My question. What should I refactor in this ugly code(I think)?
For example. When I try do duplicate a Twitter Update I got this error:
Traceback (most recent call last):
File "C:\Users\anlopes\workspace\redes_sociais\src\twitterC.py", line 42, in <module>
x.updateTwitterStatus({"url": "http://xxx.com/?cat=49", "msg": "Searching for some ...? "})
File "C:\Users\anlopes\workspace\redes_sociais\src\twitterC.py", line 35, in updateTwitterStatus
status = api.PostUpdate(update) # Fazer o update
File "C:\home_python\python_virtualenv\lib\site-packages\twitter.py", line 2549, in PostUpdate
self._CheckForTwitterError(data)
File "C:\home_python\python_virtualenv\lib\site-packages\twitter.py", line 3484, in _CheckForTwitterError
raise TwitterError(data['error'])
twitter.TwitterError: Status is a duplicate.
How can I for example catch this error in Python?
Some clues needed.
Best Regards,
As the output states clearly, your code is raising a twitter.TwitterError exception. You catch it like this:
try:
# yadda yadda
except twitter.TwitterError:
# exception code
else:
# happy flow code, optionally.
finally:
# must-run code, optionally
Now, when you are writing your first class and don't know how to catch exceptions in a language, you don't try to fetch twitter updates and save them in a database. You print "Hello World!". Go do a tutorial :D.
One possibility would be to write a function that connects to and disconnects from the database and during the connection time does some stuff. It could look something like this:
class DBFactory(object):
def DBConnection(self, Func, args):
database = sqlite3.connect('database.db') # Create a database file
cursor = database.cursor() # Create a cursor
Func(cursor, args)
database.commit() # Save our changes
database.close() # Close the connection to the database
Now the Func and args parameter actually do the interaction to the database. For example something like this:
def CreateTable(cursor, args):
cursor.execute("CREATE TABLE IF NOT EXISTS {0};".format(args)) # Make a table
Now if you wish to create a table you simple have to make this call:
f = DBFactory()
f.DBConnection(CreateTable, "twitter(id_tweet INTEGER AUTO_INCREMENT PRIMARY KEY, tweet TEXT, timestamp TEXT)"
You can proceed similarly with other interactions to the database for example inserting or deleting entries. Each time calling the DBConnection method. This should modularize your class a little better. At least in my opinion.
Please note that I did not give this code above a try, so there might be a typo in there, but I hope you get the idea. I hope this helped ya
Cherio
Woltan
The first thing to refactor is to get this code out of a class. It has absolutely no need to be in one. This should be a module, with standalone functions.
Edit to add more explanation In Python, most code is grouped naturally into modules. Classes are mainly useful for when you will need discrete instances, each with their own data. This is not the case here - you are just using the class as a placeholder for related code. That's what modules are for.
If, for example, you wanted to model an individual Tweet, which knew about its own content and how to save itself into a database, that would indeed be a good use of OOP. But "stuff that's related to Twitter" is not a class, it's a module.

Categories

Resources