You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python函数调用后变量值丢失求助:SQLite数据无法跨函数使用

解决DBRead函数变量外部无法访问的问题

问题根源

你遇到的空值/未定义错误是Python变量作用域导致的:虽然你在全局作用域定义了audiofile、log_id、daytype、jobid,但在DBRead()函数内部赋值时,Python默认会创建局部变量,而非修改全局变量。函数内部的打印能正常输出,是因为访问的是局部变量,全局变量并未被更新。

另外,你的DBRead()循环会覆盖变量值,最终只保留最后一条数据,无法满足20个定时任务的需求,需要把所有任务数据存储为列表批量处理。


修复步骤

  1. 声明全局变量:在DBRead()开头用global关键字声明要修改的全局变量,明确告知Python操作的是全局作用域的变量。
  2. 安全SQL查询:用参数化查询替代字符串拼接,避免SQL注入风险。
  3. 存储所有任务数据:把数据库读取到的所有任务存入列表,方便后续批量创建定时任务。
  4. 简化播放函数:通过带参数的函数,复用同一个播放逻辑处理所有任务。

完整优化代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:50:30