I'm creating my first database with python and I'm using SQLite. I'm following the official tutorial but it's giving me the following error:
UnboundLocalError: local variable 'conn' referenced before assignment
As far as I understand this means it was call too early but I can't understand why.
Below is my code:
import sqlite3
from sqlite3 import Error
def create_connection(db_file):
""" create a database connection to a SQLite database """
try:
conn = sqlite3.connect(db_file)
print(sqlite3.version)
except Error as e:
print(e)
finally:
conn.close()
if __name__ == '__main__':
create_connection("C:\\sqlite\db\pythonsqlite.db")
That tutorial is just horrible.
Here's what's wrong with it:
1) It only works if the path C:\sqlite\db\ already exists on your machine.
2) The notation "C:\\sqlite\db\pythonsqlite.db" (even though correct) should be written as r"C:\sqlite\db\pythonsqlite.db" (notice the leading r that tells Python that this a a raw string) to minimize the chance of a failure due to an escape character (lucky the DB is not called test.db, otherwise C:\\sqlite\db\test.db would point somewhere "funny", since \t will be converted to a TAB).
3) The finally part will always be executed. Now, if your path does not exist, you will see the print unable to open database file - because the DB can not be created. If the DB can not be created, the connection can not be created. If the connection can not be created conn is not defined - but remember we will still execute the finally block.
To sum it up:
If the path does not exists, conn is not defined but conn.close() is still executed, which will result in UnboundLocalError: local variable 'conn' referenced before assignment
Related
Within my configuration file, database uri looks like this: SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{SERVER}/{NAME}".
I want to use two different values for SERVER, depending on where to deploy the code - a default value, and another value in case previous one fails. Is it possible to do so?
If you are using, for example, sqlalchemy package than code should look like:
import sqlalchemy
try:
SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{SERVER}/{NAME}"
engine = sqlalchemy.create_engine(SQLALCHEMY_URI)
except sqlalchemy.errors.TimeoutError:
print('Connection error - using another server') # or some log, alert, whatever you like
SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{ANOTHER_SERVER}/{NAME}"
engine = sqlalchemy.create_engine(SQLALCHEMY_URI)
I have a very simple piece of code:
#app.route('/read')
def db_read():
dbcursor.execute('SELECT * FROM books;')
result = dbcursor.fetchall()
return render_template('read.html', result=result)
When I start the server, everything works fine, however, if I make the changes to the database while the app is running, the changes are not reflected on /read page, the app has to be restarted to reflect them.
I expect the code to query database each time I refresh the page and the current behavior seems very counter-intuitive to me. Can someone please help?
Have you tried setting TEMPLATES_AUTO_RELOAD to true in your config? It should toggle ON when you run in debug mode but it seems like template reloading has always been a little buggy.
You should also be using the flask run --debug command as well. app.run has issues that the run command copes with.
Your cursor is intialized withing the app instance hence queries executed are saved to the instance as read only, so changes reflected to the database are persistent within the instance.
There are several workarounds to overcome this isssue.
I would recommend you to create separate module for database instance and import where ever required.
database.py
mydb = mysql.connector.connect(
host=cfg['host'],
user=cfg['user'],
passwd=cfg['password'],
database=cfg['database']
)
db = mydb.cursor()
app.py
from database import db
#app.route('/read')
def db_read():
db.execute('SELECT * FROM books;')
result = db.fetchall()
return render_template('read.html', result=result)
I am overwriting connection.notices of psycopg2.
My goal is to send a notice from a PostgreSQL trigger to my application.
In python I want to write the current stacktrace to a log file to see which python code is triggering the trigger in the database.
It works, but unfortunately I can't extract the whole stacktrace.
I only get the lines below psycopg, not the above (lines of the callers).
Here is my code:
# Overwriting connetion.notices via Django
class MyAppConfig(AppConfig):
def ready(self):
connection_created.connect(connection_created_check_for_notice_in_connection)
class ConnectionNoticeList(object):
def append(self, message):
if not 'some_magic_of_db_trigger' in message:
return
logger.warn('%s %s' % (message, ''.join(traceback.format_stack())))
def connection_created_check_for_notice_in_connection(sender, connection, **kwargs):
connection.connection.notices=ConnectionNoticeList()
I see this in the logs:
'NOTICE: some_magic_of_db_trigger: 17909
File "/snap/pycharm-community/128/helpers/pycharm/_jb_pytest_runner....ork/foo/apps.py", line 47, in append
logger.warn(\'%s %s\' % (message, \'\'.join(traceback.format_stack())))
'
traceback.format_stack() inside ConnectionNoticeList.append() extracts not the callers.
Is there a way to get the lines of the upper methods?
(This is related to an older question: Log Stacktrace of current Python Interpreter via PostgreSQL trigger)
Above code works. I see the whole traceback.
I don't know why the traceback was cut in PyCharm. In production I could see the whole traceback and I could find the broken code which modified the data in way which should not happen.
Many thanks to Daniele Varrazzo who provided the hint to overwrite connection.notices:
https://www.postgresql.org/message-id/CA%2Bmi_8a5rij_5xchPkYPFS3moAtw9i6TrwKndynWfbJ%3DkFA4fg%40mail.gmail.com
I have a hughe problem.
I created a procedure and stored it in my OracleDB.
Now I want to execute the procedure, but its not working. There is no Error-Message Occuring, it just stops and dont continue after the first callproc call. Anybody any ideas?
!Autoincrement is enabled for the whole script!
import cx_Oracle dsn= cx_Oracle.makedsn("**********,1521,"orcl")
db= cx_Oracle.connect('******','*******',dsn)
db.autocommit = True cur = db.cursor()
cur.callproc("UPDATE_MISSING_VALUES", ['GENDER','***_PRE',1])
The Procedure is found and if I change the parameters, an SQL Error occurs. But if I let it like that, nothing happens.
If I run that query in SQL-Developer, it works just fine
It works now, I have actually now idea why, but the most important thing is that it works.
Is it possible, that the reason is that I made a
COMMIT;
Statement in my DB?? After that it worked suddenly.
First I tried:
sqlite3.cursor.execute("select * from mytable where mycol=?", (myval,))
when I execute it in the shell it works. In my class method it tells me:
ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 12 supplied.
Then I tried:
sqlite3.cursor.execute("select * from mytable where mycol='%s'" % myval)
when I execute it in the shell it works. In my class method it tells me:
ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 12 supplied.
So I decided to just format the string first and then pass that in. Like this:
sqlcmd = "select * from mytable where mycol='%s'" % myval
when I execute it in the shell it works. In my class method it tells me the same error:
ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 12 supplied.
My method is defined like this:
def mymethod(self, myval):
cur = self.conn.cursor()
cur.execute( "..." ... )
....
What am I missing?
This was a "know your tools" problem. As I mentioned above in my comment, my issue was not understanding when/how pyCharm reloads modified code. I was testing my class in a python console in pyCharm. But after I changed my code it does not automatically reload the python code, but runs the cached code.
But the part that really threw me off was when it reports an error, it pulls the source code line from the current source code, not from the cached code. So my first time through I forgot the trailing command ...(myval,). When I got the error I realized my mistake and added it. I reran it and it displayed the same error, but pulled the source code in the error from my modified code. But this was not the cached code that was being executed.
I ran it on the command line and it worked (as expected). It was just not realizing that I needed to reload the python console when I made a code change.