Display SQLite output in TK python
Question: Im trying to get a row from my db to display on a tk text widget if 1 and
remove from display if 0.

The code I have so far shows the row for one card. When I scan a seccond time
I get an error of.

    
    
    SQLite objects created in a thread can be used in that same thread.The object was created in thread id 6740 and this is thread id 6320
    <traceback object at 0x02AAC418>
    <class 'sqlite3.ProgrammingError'>
    Traceback (most recent call last):
      File "C:\rfid\main2.py", line 66, in <module>
        cardmonitor.addObserver( cardobserver )
      File "C:\Python27\lib\site-packages\smartcard\CardMonitoring.py", line 105, in addObserver
        observer.update(self, (self.rmthread.cards, []))
      File "C:\rfid\main2.py", line 56, in update
        a(tag)
      File "C:\rfid\main2.py", line 25, in a
        root.mainloop()
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1017, in mainloop
        self.tk.mainloop(n)
    KeyboardInterrupt
    

Main code below

    
    
    import sqlite3 as db
    import os
    from prettytable import from_db_cursor
    from smartcard.scard import *
    from smartcard.util import toHexString
    from prettytable import from_db_cursor
    from smartcard.CardMonitoring import CardMonitor, CardObserver
    import time
    from Tkinter import Tk, BOTH, INSERT, Text
    
    def main(tag):
    
           q = "SELECT * FROM CARDS WHERE TAG=?"
           up = "UPDATE CARDS SET FLAG = (CASE WHEN FLAG=0 THEN 1 ELSE 0 END) WHERE TAG=?"
           id = "SELECT * FROM CARDS WHERE TAG=?"
           cursor.execute(q, (tag,))
           cursor.execute(up, (tag,))
           conn.commit()
           for row in cursor.execute(id, (tag,)):
            print row [1] + row[2] #debugging to console
            r1 = str(row[1])
            r2 = str(row[2])
            msg = str(r1 + r2)
            text_widget = Text(root, font='times 40 bold', bg='Green')
            text_widget.pack(fill=BOTH, expand=0)
            text_widget.tag_configure('tag-center', wrap='word', justify='center')
            text_widget.insert(INSERT, msg, 'tag-center')
            root.mainloop()
    class printobserver( CardObserver ):
        def update( self, observable, (addedcards, removedcards) ):
            previousIdString = ""
            idString = ""
            for card in addedcards:
             if addedcards:
                hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
                assert hresult==SCARD_S_SUCCESS
                hresult, readers = SCardListReaders(hcontext, [])
                assert len(readers)>0
                reader = readers[0]
                hresult, hcard, dwActiveProtocol = SCardConnect(
                 hcontext,
                 reader,
                 SCARD_SHARE_SHARED,
                 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
                hresult, response = SCardTransmit(hcard,dwActiveProtocol,[0xFF,0xCA,0x00,0x00,0x04])
                v = toHexString(response, format=0)
                tag = str(v)
                main(tag)
    conn = db.connect('cards3.db')
    root = Tk()
    while True:
     cursor = conn.cursor()
     cardmonitor = CardMonitor()
     cardobserver = printobserver()
     cardmonitor.addObserver( cardobserver )
     cardmonitor.deleteObserver( cardobserver )
     time.sleep( 2 )
    

**update:** From answers below i have now tired the following.

Moved conn.cursor into class but same. Different error being `Coursor is not
defined`

    
    
    import sqlite3 as db
    import os
    from prettytable import from_db_cursor
    from smartcard.scard import *
    from smartcard.util import toHexString
    from prettytable import from_db_cursor
    from smartcard.CardMonitoring import CardMonitor, CardObserver
    import time
    from Tkinter import Tk, BOTH, INSERT, Text
    
    def main(tag):
    
           q = "SELECT * FROM CARDS WHERE TAG=?"
           up = "UPDATE CARDS SET FLAG = (CASE WHEN FLAG=0 THEN 1 ELSE 0 END) WHERE TAG=?"
           id = "SELECT * FROM CARDS WHERE TAG=?"
           cursor.execute(q, (tag,))
           cursor.execute(up, (tag,))
           conn.commit()
           for row in cursor.execute(id, (tag,)):
            print row [1] + " has been checked " + ('in' if row[2] else 'out')
            r1 = str(row[1])
            r2 = str(row[2])
            mseg = str(r1 + r2)
            text_widget = Text(root, font='times 40 bold', bg='Green')
            text_widget.pack(fill=BOTH, expand=0)
            text_widget.tag_configure('tag-center', wrap='word', justify='center')
            text_widget.insert(INSERT, r1 + r2, 'tag-center')
            root.mainloop()
    
    class printobserver( CardObserver ):
        cursor = conn.cursor()
        def update( self, observable, (addedcards, removedcards) ):
            previousIdString = ""
            idString = ""
            for card in addedcards:
             if addedcards:
                hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
                assert hresult==SCARD_S_SUCCESS
                hresult, readers = SCardListReaders(hcontext, [])
                assert len(readers)>0
                reader = readers[0]
                hresult, hcard, dwActiveProtocol = SCardConnect(
                 hcontext,
                 reader,
                 SCARD_SHARE_SHARED,
                 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
                hresult, response = SCardTransmit(hcard,dwActiveProtocol,[0xFF,0xCA,0x00,0x00,0x04])
                v = toHexString(response, format=0)
                tag = str(v)
                main(tag)
    
    conn = db.connect('cards3.db')
    root = Tk()
    while True:
    
     cardmonitor = CardMonitor()
     cardobserver = printobserver()
     cardmonitor.addObserver( cardobserver )
     cardmonitor.deleteObserver( cardobserver )
     time.sleep( 2 )
    

Have also tired putting in main and update but still same error

    
    
    def main(tag):
           cursor = conn.cursor
           q = "SELECT * FROM CARDS WHERE TAG=?"
           up = "UPDATE CARDS SET FLAG = (CASE WHEN FLAG=0 THEN 1 ELSE 0 END) WHERE TAG=?"
           id = "SELECT * FROM CARDS WHERE TAG=?"
           cursor.execute(q, (tag,))
           cursor.execute(up, (tag,))
           conn.commit()
           for row in cursor.execute(id, (tag,)):
            print row [1] + " has been checked " + ('in' if row[2] else 'out')
            r1 = str(row[1])
            r2 = str(row[2])
            mseg = str(r1 + r2)
            text_widget = Text(root, font='times 40 bold', bg='Green')
            text_widget.pack(fill=BOTH, expand=0)
            text_widget.tag_configure('tag-center', wrap='word', justify='center')
            text_widget.insert(INSERT, r1 + r2, 'tag-center')
            root.mainloop()
    
    def update( self, observable, (addedcards, removedcards) ):
                previousIdString = ""
                idString = ""
                for card in addedcards:
                 if addedcards:
                    hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
                    assert hresult==SCARD_S_SUCCESS
                    hresult, readers = SCardListReaders(hcontext, [])
                    assert len(readers)>0
                    reader = readers[0]
                    hresult, hcard, dwActiveProtocol = SCardConnect(
                     hcontext,
                     reader,
                     SCARD_SHARE_SHARED,
                     SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
                    hresult, response = SCardTransmit(hcard,dwActiveProtocol,[0xFF,0xCA,0x00,0x00,0x04])
                    v = toHexString(response, format=0)
                    tag = str(v)
                    main(tag)
                    cursor = conn.cursor
    

If i remove all the TK stuff and put `cursor = conn.cursor` above `while
True:` I can keep scanning cards with no issues

    
    
    def main(tag):
               cursor = conn.cursor
               q = "SELECT * FROM CARDS WHERE TAG=?"
               up = "UPDATE CARDS SET FLAG = (CASE WHEN FLAG=0 THEN 1 ELSE 0 END) WHERE TAG=?"
               id = "SELECT * FROM CARDS WHERE TAG=?"
               cursor.execute(q, (tag,))
               cursor.execute(up, (tag,))
               conn.commit()
               for row in cursor.execute(id, (tag,)):
                print row [1] + " has been checked " + ('in' if row[2] else 'out')
    


Answer: `SQLite objects created in a thread can be used in that same thread.The object
was created in thread id 6740 and this is thread id 6320`

`class printobserver(CardObserver)` has to be creating a new thread, `sqlite3`
does not support much concurrency. However, it does across different
processes. Notice this snip from your code:

**printobserver**

    
    
    main(tag)
    

**main**

    
    
    q = "SELECT * FROM CARDS WHERE TAG=?"
           up = "UPDATE CARDS SET FLAG = (CASE WHEN FLAG=0 THEN 1 ELSE 0 END) WHERE TAG=?"
           id = "SELECT * FROM CARDS WHERE TAG=?"
           cursor.execute(q, (tag,))
           cursor.execute(up, (tag,))
           conn.commit()
    

**global namespace`while-loop`**

    
    
     cardobserver = printobserver()
     cardmonitor.addObserver( cardobserver )
     cardmonitor.deleteObserver( cardobserver )
    

Since you are calling `main()` from your `printobserver` object (clearly this
object is creating a new thread each time), you spawned `cursor` in the main
thread in the global namespace, and you are calling cursor within `main()`
which is now executed from a new thread, you are getting this error.

Since you are not using the `cursor` externally from `main()`, I recommend
connecting to the database at the top of `main()`, initializing the `cursor`,
then doing whatever you need to do, and disconnecting from the database at the
bottom of main. Alternatively, you can do this within the `printobserver`
object, as the cursor initialization will still be within the same thread as
`main()`.

