RPi - Python Curses 程序 运行 在启动时没有键盘焦点
RPi - Python Curses program running at boot does not have keyboard focus
我正在尝试编写一个程序,当我的 raspberry pi 启动时,它会 运行 并允许我立即开始使用键盘输入内容,并让程序接收它。我不想在 pi 启动时手动启动程序。我需要使用 curses(或类似的无缓冲键盘输入库),因为我在 2x16 I2C LCD 上显示我正在输入的内容,但我还需要将我正在输入的所有内容记录到文本文件中。
现在,我通过在 rc.local 中输入一行来在启动时自动启动程序。这有效,I2C 显示器正确显示程序输出,但它不响应键盘输入,而是显示键盘输入(当我将馅饼连接到屏幕时,目标是 运行 无头)在一个奇怪的控制台布局上,当我按 enter 并说 -bash: 'whatever I just typed' command not found 时退出。
我已经试过了:
在程序开始时设置一个计时器,等待 pi 完全启动后再初始化 curses window 和键盘捕获
创建一个单独的 python 程序以等待 pi 完全启动,然后 运行通过导入主脚本
虽然这些方法都不起作用,但我遇到了同样的问题,只是略有不同。
需要说明的是,如果我从命令行手动 运行 该程序可以完美运行。但是当我使用 rc.local 自动启动脚本时,程序没有键盘输入(或者至少不是应该输入的地方)。
我的代码:
#!/usr/bin/python
import I2C_LCD_driver, datetime, sys
from time import *
from subprocess import call
mylcd = I2C_LCD_driver.lcd()
for x in range(30): #waits for raspberry pi to boot up
mylcd.lcd_display_string("Booting Up: "+str(x), 1)
sleep(1)
import curses
key = curses.initscr()
curses.cbreak()
curses.noecho()
key.keypad(1)
key.nodelay(1)
escape=0
while escape==0:
#variable initialization
while 1:
k=key.getch()
if k>-1: #runs when you hit any key. getch() returns -1 until a key is pressed
if k==27: #exits the program when you hit Esc
break
elif k==269:
# a couple other special Function key cases are here
else:
inpt=chr(k)
mylcd.lcd_display_string(inpt,2,step) #writes the last character to the display
#some more code that handles writing the text to the LCD, which works flawlessly when run manually.
file.write("%s\r\n" % entry)
file.close()
mylcd.lcd_display_string("Saved ",2)
mylcd.lcd_display_string("F1 New F2 PwrOff",1)
while 1:
k=key.getch()
if k>-1:
if k==265: #do it again! with F1
mylcd.lcd_clear()
break
elif k==266: #shut down with F2
escape=1
break
curses.nocbreak()
key.keypad(0)
curses.echo()
curses.endwin()
call("sudo shutdown -h now", shell=True)
如果这很重要,我在 /etc/rc.local 中的行如下:
sudo python3 journal.py &
之后是 'exit 0' 行。
感谢您的任何帮助,您可以提供。我知道这是一个非常具体的问题,重现起来很乏味,但如果有人对自动启动功能有所了解,我将非常感谢任何提示。
这应该是因为你调用程序的方式:
python3 journal.py &
您可能需要查看 bash(或您的 shell)手册页的 JOB CONTROL:
Only foreground
processes are allowed to read from ... the terminal. Background processes which
attempt to read from ... the
terminal are sent a SIGTTIN ... signal by the kernel's terminal
driver, which, unless caught, suspends the process.
简而言之,一旦 curses(或与此相关的任何东西)尝试从 stdin
中读取,您的进程可能会停止(在它可能已经写入您的显示器之后)。将它放在前台以便能够使用 stdin
(并通过扩展键盘)。
旁注:不确定在您的情况下 rc.local
的发行版和实施细节,但初始化脚本通常 运行 已经 uid/gid 0(不包装个人通过 sudo
?)
调用
好的,实际上我所要做的(在对 stackexchange 进行更多研究后我确实发现了这一点, 是包含我正在寻找的答案的线程)是 运行 我的程序来自 ~/.bashrc 而不是 /etc/rc.local。这种方法非常有效,正是我想要的。
我正在尝试编写一个程序,当我的 raspberry pi 启动时,它会 运行 并允许我立即开始使用键盘输入内容,并让程序接收它。我不想在 pi 启动时手动启动程序。我需要使用 curses(或类似的无缓冲键盘输入库),因为我在 2x16 I2C LCD 上显示我正在输入的内容,但我还需要将我正在输入的所有内容记录到文本文件中。
现在,我通过在 rc.local 中输入一行来在启动时自动启动程序。这有效,I2C 显示器正确显示程序输出,但它不响应键盘输入,而是显示键盘输入(当我将馅饼连接到屏幕时,目标是 运行 无头)在一个奇怪的控制台布局上,当我按 enter 并说 -bash: 'whatever I just typed' command not found 时退出。
我已经试过了:
在程序开始时设置一个计时器,等待 pi 完全启动后再初始化 curses window 和键盘捕获
创建一个单独的 python 程序以等待 pi 完全启动,然后 运行通过导入主脚本
虽然这些方法都不起作用,但我遇到了同样的问题,只是略有不同。
需要说明的是,如果我从命令行手动 运行 该程序可以完美运行。但是当我使用 rc.local 自动启动脚本时,程序没有键盘输入(或者至少不是应该输入的地方)。
我的代码:
#!/usr/bin/python
import I2C_LCD_driver, datetime, sys
from time import *
from subprocess import call
mylcd = I2C_LCD_driver.lcd()
for x in range(30): #waits for raspberry pi to boot up
mylcd.lcd_display_string("Booting Up: "+str(x), 1)
sleep(1)
import curses
key = curses.initscr()
curses.cbreak()
curses.noecho()
key.keypad(1)
key.nodelay(1)
escape=0
while escape==0:
#variable initialization
while 1:
k=key.getch()
if k>-1: #runs when you hit any key. getch() returns -1 until a key is pressed
if k==27: #exits the program when you hit Esc
break
elif k==269:
# a couple other special Function key cases are here
else:
inpt=chr(k)
mylcd.lcd_display_string(inpt,2,step) #writes the last character to the display
#some more code that handles writing the text to the LCD, which works flawlessly when run manually.
file.write("%s\r\n" % entry)
file.close()
mylcd.lcd_display_string("Saved ",2)
mylcd.lcd_display_string("F1 New F2 PwrOff",1)
while 1:
k=key.getch()
if k>-1:
if k==265: #do it again! with F1
mylcd.lcd_clear()
break
elif k==266: #shut down with F2
escape=1
break
curses.nocbreak()
key.keypad(0)
curses.echo()
curses.endwin()
call("sudo shutdown -h now", shell=True)
如果这很重要,我在 /etc/rc.local 中的行如下:
sudo python3 journal.py &
之后是 'exit 0' 行。 感谢您的任何帮助,您可以提供。我知道这是一个非常具体的问题,重现起来很乏味,但如果有人对自动启动功能有所了解,我将非常感谢任何提示。
这应该是因为你调用程序的方式:
python3 journal.py &
您可能需要查看 bash(或您的 shell)手册页的 JOB CONTROL:
Only foreground processes are allowed to read from ... the terminal. Background processes which attempt to read from ... the terminal are sent a SIGTTIN ... signal by the kernel's terminal driver, which, unless caught, suspends the process.
简而言之,一旦 curses(或与此相关的任何东西)尝试从 stdin
中读取,您的进程可能会停止(在它可能已经写入您的显示器之后)。将它放在前台以便能够使用 stdin
(并通过扩展键盘)。
旁注:不确定在您的情况下 rc.local
的发行版和实施细节,但初始化脚本通常 运行 已经 uid/gid 0(不包装个人通过 sudo
?)
好的,实际上我所要做的(在对 stackexchange 进行更多研究后我确实发现了这一点,