5

First time python user here, be gentle.... ;-)

Python 2.6 on OSX

Got a class which just has some wrappers around sqlite... here it is

from pysqlite2 import dbapi2 as sqlite

class SqliteDB:
    connection = ''
    curser = ''

    def connect(self):
        try:
            self.connection = sqlite.connect("pagespeed.sqlite")
            self.curser = self.connection.cursor()
         except sqlite.Error, e:
            print "Ooops: ", e.args[0]

    def find_or_create(self, table, column, value):
        self.curser.execute("SELECT id FROM ? WHERE ?=? LIMIT 1", (table, column, value))
        records = self.curser.fetchall()
        if records.count() == false:
            self.curser.execute("INSERT into ? SET ?=?", (table, column, value))
            self.curser.execute("SELECT id FROM ? WHERE ?=? LIMIT 1", (table, column, value))
        print records

and I call it like this in a separate file

import sqlitedb

def main():
    db = sqlitedb.SqliteDB()
    db.connect    
    url_id = db.find_or_create('urls', 'url', 'http://www.example.com')

however I get this error,

Traceback (most recent call last):

  File "update_urls.py", line 17, in <module>

  main()

  File "update_urls.py", line 11, in main

  url_id = db.find_or_create('urls', 'url', 'http://www.example.com')

  File "....../sqlitedb.py", line 16, in find_or_create

  self.curser.execute("SELECT id FROM ? WHERE ?=? LIMIT 1", (table, column, value))

AttributeError: 'str' object has no attribute 'execute'

So it's almost like self.curser is not getting a curser, or is self not correct?

Not to sure if what I am doing is right here....

cheers

3
  • 4
    You may think it amusing to use curser as a variable name but anyone who needs to read your code will be cursing your name as they nut through the code to detect whether it's a typo for cursor or not. Commented Oct 23, 2010 at 22:08
  • Sorry my mistake, I was going for cursor but my english is that bad... and it's my only language (english). Poor form to not know how to spell properly at my age. Commented Oct 23, 2010 at 23:16
  • Thanks all for the great feedback as well, just about to duck out for 10 mins and will check and award the answer when i'm back. I also VERY much appreciate the feedback on other sections of code, very helpful Commented Oct 23, 2010 at 23:22

4 Answers 4

7

I don't know what's wrong, but at the very least:

db.connect  

should be

db.connect()

e.g. call the function.

OK. S.Lott had the answer, I just found an other bug :)

Sign up to request clarification or add additional context in comments.

7 Comments

No... you found the bug, S. Lott found a nitpick. With his correction, OP will just get the same error but with NoneType instead of str.
er, scratch that. OP would get an AttributeError. Popped into my head when thinking about something completely different. Ad it is good advice.
@aaronsterling: Huh? You were right first time. Previously, self.curser refers to class attribute, value ''. After S.Lott change (but not fixing not calling connect method): instance attribute, value None. So: from AttributeError: 'str' object has no attribute 'execute' to AttributeError: 'NoneType' object has no attribute 'execute'
@John Machin, no because the change moves the creation of connection and curser_sic into the connect method which is never called. When find_or_create is then called, you should get AttributeError: 'SqliteDB' object has not attribute 'curser_sic'. right? So it's still an Attribute error, just with a different attribute.
@aaronsterling: You are correct as to outcome. @S.Lott moved the creation of those 2 into the __init__ method, which would be called, not the connect method. However @S.Lott also changed from curser_sic to cursor on the way to the __init__. Had he not done that, the outcome would have been as you suggested initially.
|
4

Do Not Do This.

class SqliteDB:
    connection = ''
    curser = ''

It doesn't "declare" any variables. This isn't C++ or Java.

Do this.

class SqliteDB:
    def __init__( self ):
        self.connection = None
        self.cursor= None

2 Comments

Actually, it declares class variables (accessible through self.connection or SqliteDB.connection). As soon as you write to self.connection you create an instance variable (meaning only SqliteDB.connection will access the class variable now).
Zooba: You're very close. It declares nothing. It creates class level variables that are concealed by instance variables. It's a common mistake.
1

And the 3rd bug:

self.curser.execute("SELECT id FROM ? WHERE ?=? LIMIT 1", (table, column, value))

You can't parameterise table names and column names. All you can parameterise are things that can be an expression in SQL syntax. You'll need to do something like this:

sql = "SELECT id FROM %s WHERE %s = ? LIMIT 1" % (table, column)
self.curser.execute(sql, (value, ))

Oh yeah, to save the flurry of comments: or use the modern string.format(data) method instead of the antique string % data operator.

2 Comments

string.format(data) was python 3 I thought? I will recheck but from my OP I am using 2.6. Thanks for the feedback.
1

I will also add that this will not work :

curser.execute("SELECT id FROM ? WHERE ?=? LIMIT 1", (table, column, value))

because placeholders (?) doesn't work for table name, you should rather use string formatting before if you still want to use table name as parameter:

query = "SELECT id FROM %s WHERE %s=? LIMIT 1" % (table, column)
curser.execute(query, (value, ))

and one last thing "curser" is misspelled :)

1 Comment

great thanks for the feedback, my poor spelling as well :) thnks for your time

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.