Python函数调用后变量值丢失求助:SQLite数据无法跨函数使用
解决DBRead函数变量外部无法访问的问题
问题根源
你遇到的空值/未定义错误是Python变量作用域导致的:虽然你在全局作用域定义了audiofile、log_id、daytype、jobid,但在DBRead()函数内部赋值时,Python默认会创建局部变量,而非修改全局变量。函数内部的打印能正常输出,是因为访问的是局部变量,全局变量并未被更新。
另外,你的DBRead()循环会覆盖变量值,最终只保留最后一条数据,无法满足20个定时任务的需求,需要把所有任务数据存储为列表批量处理。
修复步骤
- 声明全局变量:在
DBRead()开头用global关键字声明要修改的全局变量,明确告知Python操作的是全局作用域的变量。 - 安全SQL查询:用参数化查询替代字符串拼接,避免SQL注入风险。
- 存储所有任务数据:把数据库读取到的所有任务存入列表,方便后续批量创建定时任务。
- 简化播放函数:通过带参数的函数,复用同一个播放逻辑处理所有任务。
完整优化代码
import glob import schedule import time import sqlite3 import pygame from pygame import mixer pygame.mixer.init() curr_daytype = 'Regular' # 全局变量保留,但需在函数内声明修改 audiofile = '' log_id = '' daytype = '' jobid = '' #==========================================FUNCTIONS===========================================# def DBRead(): # 声明要修改的全局变量 global log_id, daytype, audiofile, jobid conn = sqlite3.connect('pythontut.db') cursor = conn.cursor() # 参数化SQL查询,避免注入 sql = "SELECT * FROM anno WHERE daytype = ?" cursor.execute(sql, (curr_daytype,)) fetch = cursor.fetchall() all_tasks = [] for data in fetch: log_id = data[0] daytype = data[1] rec_time = data[2] audiofile = data[3] print(log_id, daytype, rec_time, audiofile) # 把每条任务存入列表 all_tasks.append({ "log_id": log_id, "daytype": daytype, "rec_time": rec_time, "audiofile": audiofile }) cursor.close() conn.close() jobid = log_id return all_tasks # 通用播放函数,接收任务参数 def play_audio(task): print(f"任务{task['log_id']}播放中: {task['audiofile']}") # 避免路径带多余引号 mixer.music.load(task['audiofile']) mixer.music.play(1) #============================================VARIABLES=============================================# audiolist = glob.glob("audio/*.mp3") print(audiolist) # 读取所有任务并创建定时任务 all_tasks = DBRead() for task in all_tasks: # 跳过空音频路径的任务 if task['audiofile']: schedule.every().day.at(task['rec_time']).do(play_audio, task=task) #==============================================TEST CODES==========================================# # 保留原有测试任务 schedule.every().day.at("12:45").do(lambda: print("file1.wav Playing...") or mixer.music.load("1-start.mp3") or mixer.music.play(1)) schedule.every().day.at("13:07").do(lambda: print("file2.wav Playing...") or mixer.music.load("1-end.mp3") or mixer.music.play(1)) schedule.every().day.at("14:31").do(lambda: print("2-start.mp3 Playing...") or mixer.music.load("7-end.mp3") or mixer.music.play(1)) schedule.every().day.at("14:31").do(lambda: print("2-end.mp3 Playing...") or mixer.music.load("8-start.mp3") or mixer.music.play(1)) while True: schedule.run_pending() time.sleep(1)
关键说明
- 全局变量在函数内通过
global声明后,赋值会同步到全局作用域,外部访问不再为空。 - 用列表存储所有任务数据,循环创建定时任务,无需手动写20个
jobX函数。 - 参数化SQL查询
cursor.execute(sql, (curr_daytype,))比字符串拼接更安全,避免特殊字符导致的SQL语法错误或注入。 - 播放函数通过接收任务参数实现复用,解决了不同任务的音频路径和时间差异化问题。
内容的提问来源于stack exchange,提问作者Sarath kumar
相关产品推荐
相关产品推荐

