如何修复Systemd启动Python脚本时的IndexError: list index out of range错误
问题描述
原本正常运行的OLED脚本,添加随机运行Luma Examples脚本的功能后,通过systemd启动时出现报错,但在Geany中运行正常。
初始错误日志
crawl_oled.service - test OLED SSD1306 Loaded: loaded (/lib/systemd/system/crawl_oled.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Wed 2024-03-06 08:30:14 EST; 2min 33s ago Process: 200235 ExecStartPre=/bin/sleep 30 (code=exited, status=0/SUCCESS) Process: 200600 ExecStart=/usr/bin/python3 /home/pi/luma-env/luma.examples/examples/OLED_INFO.py (code=exited, status=1/FAILURE) Main PID: 200600 (code=exited, status=1/FAILURE) CPU: 609ms Mar 06 08:30:14 raspberrypi python3[200600]: Traceback (most recent call last): Mar 06 08:30:14 raspberrypi python3[200600]: File "/home/pi/luma-env/luma.examples/examples/OLED_INFO.py", line 299, in <module> Mar 06 08:30:14 raspberrypi python3[200600]: run_ext() Mar 06 08:30:14 raspberrypi python3[200600]: File "/home/pi/luma-env/luma.examples/examples/OLED_INFO.py", line 59, in run_ext Mar 06 08:30:14 raspberrypi python3[200600]: random_py = random.choice(Local_List) Mar 06 08:30:14 raspberrypi python3[200600]: File "/usr/lib/python3.9/random.py", line 347, in choice Mar 06 08:30:14 raspberrypi python3[200600]: return seq[self._randbelow(len(seq))] Mar 06 08:30:14 raspberrypi python3[200600]: IndexError: list index out of range Mar 06 08:30:14 raspberrypi systemd[1]: crawl_oled.service: Main process exited, code=exited, status=1/FAILURE Mar 06 08:30:14 raspberrypi systemd[1]: crawl_oled.service: Failed with result 'exit-code'.
系统信息
pi@raspberrypi:~ $ cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 11 (bullseye)" NAME="Debian GNU/Linux" VERSION_ID="11" VERSION="11 (bullseye)" VERSION_CODENAME=bullseye ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"
问题代码片段
def run_ext(): i = 0 while True: try: # Command to run "OTHER".py ####random_file=random.choice(os.listdir()) Local_List = [each for i, each in enumerate(os.listdir(current_working_directory)) if each.endswith('1.py')] random_py = random.choice(Local_List) random_py = current_working_directory + '/' + str(random_py) print(random_py) sp.run(random_py, timeout=10) except sp.TimeoutExpired: break
修改后的错误日志
修改为random_py = random.choice(Local_List[i])后,报错如下:
crawl_oled.service - test OLED SSD1306 Loaded: loaded (/lib/systemd/system/crawl_oled.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Wed 2024-03-06 08:52:57 EST; 2s ago Process: 216809 ExecStartPre=/bin/sleep 30 (code=exited, status=0/SUCCESS) Process: 217172 ExecStart=/usr/bin/python3 /home/pi/luma-env/luma.examples/examples/OLED_INFO.py (code=exited, status=1/FAILURE) Main PID: 217172 (code=exited, status=1/FAILURE) CPU: 545ms Mar 06 08:52:56 raspberrypi systemd[1]: Started test OLED SSD1306. Mar 06 08:52:57 raspberrypi python3[217172]: / Mar 06 08:52:57 raspberrypi python3[217172]: Traceback (most recent call last): Mar 06 08:52:57 raspberrypi python3[217172]: File "/home/pi/luma-env/luma.examples/examples/OLED_INFO.py", line 299, in <module> Mar 06 08:52:57 raspberrypi python3[217172]: run_ext() Mar 06 08:52:57 raspberrypi python3[217172]: File "/home/pi/luma-env/luma.examples/examples/OLED_INFO.py", line 59, in run_ext Mar 06 08:52:57 raspberrypi python3[217172]: random_py = random.choice(Local_List[i]) Mar 06 08:52:57 raspberrypi python3[217172]: IndexError: list index out of range Mar 06 08:52:57 raspberrypi systemd[1]: crawl_oled.service: Main process exited, code=exited, status=1/FAILURE Mar 06 08:52:57 raspberrypi systemd[1]: crawl_oled.service: Failed with result 'exit-code'.
需求
实现从Luma Examples文件夹中随机选择一个示例运行10秒,然后继续执行main()的剩余部分。
解决方案
核心问题分析
报错IndexError: list index out of range的根本原因是**Local_List为空**:
- systemd服务默认工作目录是根目录
/,如果current_working_directory依赖相对路径或os.getcwd()获取,会指向根目录,而根目录下没有符合*.1.py的文件。 - Geany运行时工作目录是脚本所在的
/home/pi/luma-env/luma.examples/examples/,所以能正常找到文件。
修复步骤
- 固定脚本目录路径:直接使用脚本所在的绝对路径定位目标文件夹,不依赖当前工作目录。
- 添加空列表判断:避免无符合条件文件时触发报错。
- 修正
random.choice用法:该函数接收列表本身,不需要额外索引。
修复后的代码
import os import random import subprocess as sp def run_ext(): # 获取当前脚本所在的绝对目录 script_dir = os.path.dirname(os.path.abspath(__file__)) # 筛选所有以1.py结尾的文件 local_list = [f for f in os.listdir(script_dir) if f.endswith('1.py')] # 判断列表是否为空,提前返回避免报错 if not local_list: print("未找到符合条件的.py文件") return # 随机选择一个文件并拼接完整路径 random_py = random.choice(local_list) random_py_path = os.path.join(script_dir, random_py) try: print(f"运行脚本: {random_py_path}") # 运行脚本10秒后超时退出 sp.run(["python3", random_py_path], timeout=10) except sp.TimeoutExpired: print("脚本运行超时,结束执行") # 执行完成后自动返回,继续main()剩余逻辑
额外优化
如果systemd服务仍有异常,可以在crawl_oled.service配置中指定工作目录:
[Service] WorkingDirectory=/home/pi/luma-env/luma.examples/examples/ ExecStart=/usr/bin/python3 /home/pi/luma-env/luma.examples/examples/OLED_INFO.py
内容的提问来源于stack exchange,提问作者user23545286
相关产品推荐
相关产品推荐

