鱼C论坛

 找回密码
 立即注册
查看: 49|回复: 2

Flask+Sqlite3相关问题求助

[复制链接]
发表于 前天 18:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Code

  1. import sqlite3
  2. from queue import Queue
  3. from typing import Any
  4. from flask import Flask, request, send_file
  5. from threading import Thread

  6. class SQLiteExecutor:
  7.     """SQLite3 仅支持在同一线程内操作,但 flask 的机制使其并不在同一线程内,故封装此类以解决此问题"""
  8.     def __init__(self, path: str):
  9.         """
  10.         :param path: SQLite3 文件路径
  11.         """
  12.         self.path = path
  13.         # 每次需要执行的时候都往 Queue 里扔东西就行
  14.         self.queue = Queue()
  15.         # 执行完之后把结果放到这里
  16.         self.results = Queue()
  17.         # 把所有操作都封装到 _thread 方法里,这样就不会报错了
  18.         Thread(target=self._thread, daemon=True).start()
  19.    
  20.     def _thread(self) -> None:
  21.         """线程函数。
  22.         
  23.         `_thread()` 一直监听 `queue`,当 `queue` 发生改变时 `_thread()` 就会自动执行里面的函数。
  24.         
  25.         执行完函数后,`_thread` 会立即把结果(如有)放到 `results` 里,所以理论上不存在等待时间。
  26.         """
  27.         while True:
  28.             conn = sqlite3.connect(self.path)
  29.             cur = conn.cursor()
  30.             if (result := self.queue.get()(conn, cur)) is not None:
  31.                 self.results.put(result)
  32.    
  33.     def do(self, command: str, commit: bool = True) -> None:
  34.         """对 `cur` 执行一条命令。
  35.         
  36.         `do()` 的原理是将 `_execute()` 的返回值放到 `queue` 里,`_thread` 在监听到有元素进入时就会自动执行它。
  37.         当 `_thread` 执行完毕后,它会把结果放到 `results` 里,只要监听 `results` 即可。
  38.         
  39.         :param command: SQLite3 命令
  40.         :param commit: 命令执行完后是否要 commit
  41.         :return: 无
  42.         """
  43.         def inner(conn: sqlite3.Connection, cur: sqlite3.Cursor):
  44.             cur.execute(command)
  45.             if commit:
  46.                 conn.commit()
  47.         self.queue.put(inner)
  48.    
  49.     def cur(self, name: str) -> Any:
  50.         """让 `cur` 执行 `name`。
  51.         
  52.         :param name: 例如 `name == 'fetchall'`,执行 `cur.fetchall()`。
  53.         :return: 执行的结果
  54.         """
  55.         def inner(_: sqlite3.Connection, cur: sqlite3.Cursor):
  56.             return getattr(cur, name)()
  57.         self.queue.put(inner)
  58.         return self.results.get()

  59. ext = SQLiteExecutor('data.db')
  60. ext.do('''CREATE TABLE IF NOT EXISTS users (
  61.     id INTEGER PRIMARY KEY AUTOINCREMENT,
  62.     name TEXT NOT NULL,
  63.     pwd VARCHAR(64) NOT NULL
  64. )''')

  65. def add_route(route_path: str, file_path: str = '') -> None:
  66.     """添加一条 route。

  67.     调用这个函数,可以不用单独为每个 route 写一个函数,程序使用变量 `_rid` 自动为每个 route 分配名称。
  68.    
  69.     :param route_path: 用户想要看到对应文件应该访问的***网址***
  70.     :param file_path: 用户访问网住可以看到的文件的***路径***
  71.     """
  72.     global _rid
  73.     file_path = (file_path or route_path).lstrip('/')
  74.     exec(f'''@app.route({repr(route_path)})
  75. def route{_rid}():
  76.     return send_file({repr(file_path)})
  77. ''')
  78.     _rid += 1

  79. def read(path: str) -> str:
  80.     """读取一个文本文件的内容。
  81.    
  82.     调用此函数可以避免大量重复 with-as 语句,不仅让代码变多,还降低了可读性,敲起来也十分乏味。
  83.    
  84.     :param path: 文本文件的路径
  85.     :return: 文本文件的内容
  86.     """
  87.     with open(path, encoding='utf-8') as f:
  88.         return f.read()

  89. _rid = 0
  90. app = Flask(__name__)

  91. add_route('/favicon.ico')
  92. add_route('/base.css')
  93. add_route('/daohanglan.js')

  94. @app.route('/')
  95. def main():
  96.     return read('index.html'), 200

  97. @app.route('/submit', methods=['POST'])
  98. def handler():
  99.     json = request.get_json()
  100.     try:
  101.         # todo 代表用户要做的请求
  102.         todo = json['todo']
  103.         if todo == 'login':
  104.             # 用户想要登录
  105.             # 密码 pwd 是 SHA256 加密后的样子
  106.             name, pwd = json['name'], json['pwd']
  107.             ext.do(f"SELECT * FROM users", False)
  108.             print(ext.cur('fetchall'))
  109.         elif todo == 'register':
  110.             # 注册
  111.             # 密码 pwd 是 SHA256 加密后的样子
  112.             name, pwd = json['name'], json['pwd']
  113.             ext.do(f"INSERT INTO users (name, pwd) VALUES ('{name}', '{pwd}');")
  114.     except KeyError as ex:
  115.         return f'400 Bad Request (Key {repr(ex.args[0])} Not Found)', 400
  116.     return str(), 200

  117. if __name__ == '__main__':
  118.     app.run(port=22222, debug=True)
复制代码


输出的是空列表 [],数据库里已经有数据了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 昨天 18:31 | 显示全部楼层
@FishC 求救
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 18:33 | 显示全部楼层


Python反转字符串的两种常用方法

这里提供两种简单易懂的实现方式,根据需求选择即可:

  • 切片法(推荐)
    直接通过切片操作[::-1]实现反转:

    1. s = "FishC"
    2. reversed_str = s[::-1]
    3. print(reversed_str)  # 输出:ChsiF
    复制代码

  • reversed函数法
    使用内置函数生成反转后的迭代器,再拼接字符串:

    1. s = "hello"
    2. reversed_str = ''.join(reversed(s))
    3. print(reversed_str)  # 输出:olleh
    复制代码



注意:
1. 两种方法都不会修改原字符串(字符串不可变)
2. 切片法性能更优,适合简单场景
3. reversed函数在处理复杂对象时更灵活

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-20 13:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表