Orange Pi 5 Debian下Python Web应用启动权限与Xlib连接问题
Orange Pi 5 Debian系统Python应用启动异常解决方案
问题1:普通用户运行触发PermissionError(GPIO权限不足)
报错信息
orangepi@orangepi5:~$ python3 /home/orangepi/v-link/V-Link.py
Initializing backend...
Traceback (most recent call last):
File "/hone/orangeps/v-Link/V-Link.py", line 9, in
from backend.adc import ADCThread
File "/home/orangepi/v-Link/backend/adc.py", line 9, in
import board
...
PermissionError: [Errno 13] Permission denied
...
解决方案
- 将当前用户加入
gpio用户组,永久获取GPIO设备访问权限:sudo usermod -aG gpio $USER - 注销当前用户重新登录,使组权限生效
- 验证权限:登录后执行
groups命令,确认输出包含gpio
问题2:root用户运行触发Xlib.error.DisplayConnectionError
报错信息
Xlib.error.DisplayConnectionError: Can't connect to display ":0" : b'No protocol specified\n'
解决方案
xhost+是临时生效的方法,重启后会失效,推荐以下更安全或永久的方式:
方法1:临时允许root访问当前用户的X显示(重启后失效)
在普通用户终端执行:
xhost +si:localuser:root
之后切换到root用户运行应用即可
方法2:永久配置root访问X显示
- 编辑X服务器权限配置文件:
sudo nano /etc/X11/Xwrapper.config - 将
allowed_users=console修改为allowed_users=anybody - 添加一行
needs_root_rights=yes - 保存退出,重启系统后生效
方法3:运行应用时指定DISPLAY环境变量
在root用户下执行应用时,手动指定显示变量:
DISPLAY=:0 python3 /home/orangepi/v-link/V-Link.py
应用代码(供参考)
import threading import time import sys import os sys.path.append(os.path.dirname(os.path.abspath(__file__))) from backend.server import ServerThread from backend.adc import ADCThread from backend.canbus import CanBusThread from backend.linbus import LinBusThread from backend.browser import BrowserThread from backend.dev.vcan import VCanThread from backend.shared.shared_state import shared_state class VLINK: def __init__(self): self.exit_event = shared_state.exit_event self.threads = { "VCan": VCanThread(), "Browser": BrowserThread(), "Server": ServerThread(), "Canbus": CanBusThread(), #"Linbus": LinBusThread(), "ADC": ADCThread(), } def start_thread(self, thread_name): thread_class = self.threads[thread_name].__class__ if not self.threads[thread_name].is_alive(): self.threads[thread_name] = thread_class() thread = self.threads[thread_name] thread.daemon = True thread.start() shared_state.THREAD_STATES[thread_name] = True print(f"{thread_name} thread started.") else: print(f"{thread_name} thread is already running.") def stop_thread(self, thread_name): thread = self.threads[thread_name] if thread.is_alive(): print(f"Stopping {thread_name} thread.") thread.stop_thread() thread.join() shared_state.THREAD_STATES[thread_name] = False print(f"{thread_name} thread stopped.") def toggle_thread(self, thread_name): if shared_state.THREAD_STATES[thread_name]: self.stop_thread(thread_name) else: self.start_thread(thread_name) self.print_thread_states() def join_threads(self): for thread_name in self.threads: self.stop_thread(thread_name) for thread_name, thread in self.threads.items(): if thread.is_alive(): thread.join() shared_state.THREAD_STATES[thread_name] = False print("Done.") def process_toggle_event(self): if shared_state.toggle_can.is_set(): self.toggle_thread("Canbus") shared_state.toggle_can.clear() if shared_state.toggle_adc.is_set(): self.toggle_thread("ADC") shared_state.toggle_adc.clear() if shared_state.toggle_browser.is_set(): self.toggle_thread("Browser") shared_state.toggle_browser.clear() def process_exit_event(self): if self.exit_event.is_set(): self.exit_event.clear() shared_state.toggle_browser.set() time.sleep(1) sys.exit(0) def print_thread_states(self): if(shared_state.isDev): for thread_name, thread in self.threads.items(): state = "Alive" if thread.is_alive() else "Not Alive" print(f"{thread_name} Thread: {state}") def clear_screen(): if os.name == 'nt': os.system('cls') else: os.system('clear') def non_blocking_input(prompt): try: return input(prompt) except EOFError: return None if __name__ == "__main__": vlink = VLINK() vlink.start_thread("Server") if len(sys.argv) > 1 and sys.argv[1] == "dev": shared_state.isDev = True choice = non_blocking_input("Simulate CAN-Bus? (Y/N): ") if choice.lower() == 'y': shared_state.vCan = True print("Starting VCAN...") vlink.toggle_thread("VCan") choice = non_blocking_input("Start on Vite-Port 5173? (Y/N): ") if choice.lower() == 'y': shared_state.isFlask = False choice = non_blocking_input("Start in Kiosk mode? (Y/N): ") if choice.lower() == 'n': shared_state.isKiosk = False vlink.start_thread("Canbus") time.sleep(.1) vlink.start_thread("ADC") time.sleep(3) vlink.start_thread("Browser") vlink.print_thread_states() try: while(True): vlink.process_toggle_event() vlink.process_exit_event() time.sleep(.1) except KeyboardInterrupt: print("\nExiting... Stopping threads.") #vlink.join_threads() sys.exit(0)
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

