【问题标题】:Print each queries with Sqlite & Python使用 Sqlite 和 Python 打印每个查询
【发布时间】:2016-09-09 14:50:28
【问题描述】:

我有一个带有 Tkinter 的 python 脚本,我想在后台打印在 Sqlite 数据库中执行的每个查询(只是为了好玩):

我有一个数据库对象:

import sqlite3

class Database():

    def __init__(self):
        try:
            sqlite3.enable_callback_tracebacks(True)
            self.connection = sqlite3.connect('databases.sqlite')
            self.cursor = self.connection.cursor()
            self.cursor.execute( """ CREATE TABLE ....  """ )
        except:
            print('error in database connection')

    def __del__(self):
        self.cursor.close()

还有一个任务对象

class Task():

    def __init__(self, name="no_name"):
        self.database = Database()
        data = {"name" : name }
        self.database.cursor.execute("INSERT INTO tasks(name) VALUES(:name)" , data )
        self.database.connection.commit()

当我这样做 new_task = Task('Hello') 时,我希望在 CLI 中自动输出如下:

* executed in 4ms :
    INSERT INTO tasks (name) VALUES('Hello');

有什么想法吗?提前谢谢!

【问题讨论】:

  • 附带说明,我不确定是否使用__del__ 关闭光标。也许更重要的是,你close 连接了吗?也许更好地让方法close..self.cur.close(); self.conn.close()。你是否需要在Task__init__ 方法中使用self (看起来,好像这个类没有更多内容?只是摆脱自我。也许甚至Task 太多了,函数可能就足够了see

标签: python sqlite


【解决方案1】:

这就是你要找的吗?我考虑过使用装饰器,某种stopwatch

import time

def stopwatch(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        func(*args,**kwargs)
        end = time.time()
        timed = int((end - start)*1000)
        print(timed)
    return wrapper

但后来我想到了上下文管理器,也许(我不是判断的合适人选)更适合这种工作。从 [这里][1] 借用代码我最终得到了(哈哈)这个:

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self

    def __exit__(self, *args):
        self.end = time.clock()
        # format as milliseconds 
        self.interval = int((self.end - self.start) * 1000)
        
    
class Task():

    def __init__(self, name="no_name"):
        data = {"name" : name }
        sql_template = "INSERT INTO tasks(name) VALUES(:name)"
        # do the database thingy inside the Timer context
        with Timer() as t:
            self.database = Database()
            self.database.cursor.execute(sql_template, data)
            self.database.connection.commit()
        print("* executed in {}ms :".format(t.interval))
        print("    {}".format(sql_template))

我已经对其进行了一些测试,但是将其应用于您的案例我可能会犯一些错误,因为我必须稍微更改 Task __init__ 才能重用 SQL 命令。 [1]:http://preshing.com/20110924/timing-your-code-using-pythons-with-statement/

【讨论】:

  • 是的,使用装饰器是个好主意,但是如何在任务方法(如 UPDATE 或 DELETE)上自动执行 SQL 命令?
  • 是的,我认为您适合装饰器功能。有没有办法拦截每个游标方法(如__setattr__()方法)并打印查询?
  • 后注:在执行时使用字符串格式会导致 SQL 注入,不利于应用程序的安全性。
  • @Niklas 绝对!谢谢你的收获。我已经更新了代码。它与预期不匹配 100%,因为最终打印不包含插值。但我目前无法修复它。无论如何,这也不是一个最小的工作示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2021-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多