# Run a python program at startup with keyboard support

**URL:** https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088
**Category:** Requests
**Created:** [13 March 2017 07:39 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088 "2017-03-13T07:39:49Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [13 March 2017 07:39 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/1 "2017-03-13T07:39:49Z")

</div>

Hi,  
I am evaluating DietPi to solve a problem that has happened since the Pi3 was released.  
If you run a python program at startup from /etc/rc.local that reads the keyboard you get a crash:

oldterm = termios.tcgetattr(fd)  
termios error: (25, ‘inappropriate ioctl for device’)

This did not happen with the Pi2 operating system but does with the Pi3(Pixel) and DietPi.

Is there a way to run the following program automatically at startup without it crashing?

Thanks,  
David Taylor

```nohighlight
#!/usr/bin/python
#
# startup.py
import os, sys, time
import termios, fcntl

def GetKey():
   fd = sys.stdin.fileno()
   oldterm = termios.tcgetattr(fd)
   newattr = termios.tcgetattr(fd)
   newattr[3] = newattr[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO
   newattr[6][TERMIOS.VMIN] = 1
   newattr[6][TERMIOS.VTIME] = 0
   termios.tcsetattr(fd, termios.TCSANOW, newattr)
   oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
   fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
   try:
      try:
         c = sys.stdin.read(1)
# print "Got character", repr(c)
         return c
      except IOError: pass
   finally:
      termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
      fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

if __name__ == " __main__":

   # give us a chance to quit before launching
   print '### Press q to prevent launch or any other key to launch ###'
   bLaunch = True 
   TERMIOS = termios
   i = 0
   z = 5
   while i < z:
      print z - i,   
      i = i + 1
      ch = GetKey()
      if ch != None:
         if ch == 'q':
            print
            print 'Launch has been stopped by pressing ' + ch
            bLaunch = False
         break
      time.sleep(1)
         
   if bLaunch == True:
      print
      print "Launch the main loop here"

exit(0)

```

---

<div class="post-metadata">

### Author: ![Fourdee](https://dietpi.com/forum/user_avatar/dietpi.com/fourdee/32/11_2.png) [@Fourdee](https://dietpi.com/forum/u/Fourdee)
#### Post date: [13 March 2017 13:55 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/2 "2017-03-13T13:55:35Z")

</div>

Hi David,

You need to enable StandardIntput=tty in your service, to allow for keyboard input.

**Try systemD service that allows for std tty input and output:**  
_Change /root/test.py accordingly_, then copy/paste all

```nohighlight
cat << _EOF_ > /etc/systemd/system/python.service
[Unit]
Description=Python
After=local-fs.target network.target

[Service]
Type=oneshot
RemainAfterExit=yes
StandardOutput=tty
StandardInput=tty
ExecStart=/usr/bin/python /root/test.py

[Install]
WantedBy=multi-user.target
_EOF_
systemctl enable python.service
systemctl daemon-reload

```

---

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [13 March 2017 22:40 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/3 "2017-03-13T22:40:12Z")

</div>

Thanks for your very useful reply.  
What I actually did was add the missing line  
StandardInput=tty  
to /etc/systemd/system/rc-local.service  
and now my python program starts up correctly from rc.local as it always did before “Pixel”.  
I checked in the Pixel os but it does not have a /etc/systemd/system/rc-local.service file or a /etc/systemd/system/python.service file so I could not apply the fix to it so I will stay with DietPi.

I am running my home central heating with the pi and find that SD cards do not last long. I am downloading weather data and other stuff regularly so am stressing the SD I think. As these files are temporary could I be loading them into RAM memory instead? If so, what folder should I save them to?

Thanks and all the best,  
David

---

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [14 March 2017 13:48 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/4 "2017-03-14T13:48:06Z")

</div>

Hi again,  
I was a bit hasty when I said that this problem is fixed.  
When run as I described by adding the missing line  
StandardInput=tty  
to /etc/systemd/system/rc-local.service  
keyboard presses get displayed but my python program is not seeing them. What actually happens is that my key presses are seen by the login.

When run using the python.service you suggested it starts up really early in the boot sequence then just dies.

Is it possible to automatically start a python program (that reads the keyboard) right at the end of the boot sequence after everything else has completed?

Thanks again,  
David

---

<div class="post-metadata">

### Author: ![Fourdee](https://dietpi.com/forum/user_avatar/dietpi.com/fourdee/32/11_2.png) [@Fourdee](https://dietpi.com/forum/u/Fourdee)
#### Post date: [14 March 2017 16:12 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/5 "2017-03-14T16:12:19Z")

</div>

> [@superdave156](#):
>

Hi David,

/etc/rc.local uses systemD service Type=idle. This will be launched after SystemD has finished all bootup services. So you could try idle and add After=rc.local

> When run using the python.service you suggested it starts up really early in the boot sequence then just dies.

Service type is oneshot. So SystemD will launch the python script and wait until it exits, before carrying on. You could try Type=simple which will thread this into the background.

Another way to delay start of script, add a simple sleep 10 to the start of python code.

---

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [16 March 2017 11:20 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/6 "2017-03-16T11:20:00Z")

</div>

Hi again,

Thanks for your reply. I’ve tried these suggestions but am getting nowhere. I just don’t have enough Linux knowledge.  
Having created DietPi you clearly like a challenge so if you can get the startup.py program I posted earlier to start and work from /etc/rc.local without crashing then I will make a generous donation to the DietPi cause of $100. It might be a simple thing or it might take you a while but as a hint, it worked perfectly well in the standard Raspian as supplied with all pi before pi3.

All the very best and in anticipation of success…  
David

---

<div class="post-metadata">

### Author: ![Fourdee](https://dietpi.com/forum/user_avatar/dietpi.com/fourdee/32/11_2.png) [@Fourdee](https://dietpi.com/forum/u/Fourdee)
#### Post date: [16 March 2017 14:45 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/7 "2017-03-16T14:45:14Z")

</div>

> [@superdave156](#):
>
> Hi again,
> 
> Thanks for your reply. I’ve tried these suggestions but am getting nowhere. I just don’t have enough Linux knowledge.  
> Having created DietPi you clearly like a challenge so if you can get the startup.py program I posted earlier to start and work from /etc/rc.local without crashing then I will make a generous donation to the DietPi cause of $100. It might be a simple thing or it might take you a while but as a hint, it worked perfectly well in the standard Raspian as supplied with all pi before pi3.
> 
> All the very best and in anticipation of success…  
> David

I do enjoy a challenge 🙂

Ok, so the main issue with trying to run this under rc.local, as Type=idle runs a background process, keyboard inputs will not go to your python script currently, or, take foreground blocking mode.

We’ll need to modify rc-local.service slightly, to launch prior to end of SystemD multi-user.target, instead of Type=idle

```plaintext
cat << _EOF_ > /etc/systemd/system/rc-local.service
[Unit]
Description=/etc/rc.local Compatibility
After=dietpi-boot.service dietpi-ramdisk.service dietpi-ramlog.service multi-user.target
Requires=dietpi-boot.service dietpi-ramdisk.service

[Service]
Type=oneshot
ExecStart=/etc/rc.local
StandardOutput=tty
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
_EOF_
systemctl enable rc-local.service
systemctl daemon-reload

```

Then, we create a service for your python script /root/test.py, with support for foreground process and blocking mode (Type=oneshot) and keyboard input (StandardInput=tty):

```plaintext
cat << _EOF_ > /etc/systemd/system/python.service
[Unit]
Description=Python start + foreground + keyboard input. After rc-local
Requires=multi-user.target
After=multi-user.target rc-local.service
AllowIsolate=yes

[Service]
Type=oneshot
RemainAfterExit=yes
StandardOutput=tty
StandardInput=tty
ExecStart=/usr/bin/python /root/test.py

[Install]
WantedBy=multi-user.target
_EOF_
systemctl daemon-reload
systemctl enable python.service

```

Make sure your script is in /root/test.py, then reboot system.

---

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [18 March 2017 21:24 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/8 "2017-03-18T21:24:20Z")

</div>

Thanks for this. It is almost what I need…

I created a fresh DietPi SD card, ran your scripts and added my test.py program. In test.py I set z = 50 to give a 50 second countdown and added an led flash every second so I could see that the program was running. I then rebooted.

During the boot my program started running, counted down for about 5 seconds then stopped and the login appeared.  
After I logged in I got the # prompt.

All I need now is for my test.py program to keep running and have the focus until I press a key to stop it. Then, when test.py has exited I need the login to appear. That should be possible shouldn’t it?

Thanks for your help,  
Dave

---

<div class="post-metadata">

### Author: ![Fourdee](https://dietpi.com/forum/user_avatar/dietpi.com/fourdee/32/11_2.png) [@Fourdee](https://dietpi.com/forum/u/Fourdee)
#### Post date: [19 March 2017 14:22 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/9 "2017-03-19T14:22:11Z")

</div>

> [@superdave156](#):
>
> All I need now is for my test.py program to keep running and have the focus until I press a key to stop it. Then, when test.py has exited I need the login to appear. That should be possible shouldn’t it?

Hi Dave,

Currently, test.py is being executed, then it finishes once you press a key, or, i reaches 5. As the script is finished, the login prompt appears.

You’ll need to create a loop in your python code, that waits for user input without a time limit, before the script finishes.

I dont do Python, so syntax may be incorrect, but something like this should do it:

```plaintext
   while True:
      ch = GetKey()
      if ch != None:
         if ch == 'q':
            print
            print 'Launch has been stopped by pressing ' + ch
            bLaunch = False
         break
      time.sleep(1)
exit(0)

```

---

<div class="post-metadata">

### Author: ![superdave156](https://dietpi.com/forum/letter_avatar_proxy/v4/letter/s/4491bb/32.png) [@superdave156](https://dietpi.com/forum/u/superdave156)
#### Post date: [20 March 2017 22:25 UTC](https://dietpi.com/forum/t/run-a-python-program-at-startup-with-keyboard-support/1088/10 "2017-03-20T22:25:05Z")

</div>

Hi again,

Unfortunately that didn’t make any difference however I have figured it out for myself and I think my solution would be a great feature for DietPi.

Here’s what I did:

modify /DietPi/dietpi/login

add a new function - I inserted it just ahead of Run\_Autostart()

```nohighlight
	#Autostart user's script
	Run_User_AutoStart(){
		sudo chmod 755 /root/autostart.sh
		./autostart.sh
	}

```

add a new option to function Run\_Autostart - insert this before #Uae4arm standard boot

```nohighlight
			#standard boot to Console with automatic login
			elif (( $AUTO_START_INDEX == 7 )); then
				Run_User_AutoStart

```

modify #Normal Login to this:

```nohighlight
	#----------------------------------------------------------------
	#Normal Login
	if (( $DIETPI_INSTALL_STAGE == 1 )); then

		/DietPi/dietpi/dietpi-banner 1

		if (( $AUTO_START_INDEX > 0 )); then
			Run_AutoStart
		else
			Run_User_AutoStart
		fi
	#----------------------------------------------------------------

```

save /DietPi/dietpi/login

create file /root/autostart.sh similar to this one:

```nohighlight
#!/bin/bash
#////////////////////////////////////
# DietPi autostart Script
#
#////////////////////////////////////
# Created by David Taylor / superdave156@gmail.com
#
#////////////////////////////////////
#
# Info:
# - filename /root/autostart.sh
# - activated when DietPi-config item 9 (Autostart Options) then items 0 or 7 selected.
# - Allows you to autostart your own Python program with full keyboard support - unlike Pixel!
#////////////////////////////////////
#
#////////////////////////////////////
# Add your own autostart commands here:

#for example
sudo chmod 755 /root/Python/test.py
/usr/bin/python /root/Python/test.py
exit 0

```

That’s it!

If you have the boot configured to “Console: Manual Login” then you have to login then autostart.sh runs  
If you have the boot configured to “Console: Automatic Login” then autostart.sh runs and you have a headless autostarting python program. Because the keyboard is available you can break into the program loop to work on the code.  
  
  
To add this feature to DietPi all you would need to do is apply the above mods with the python lines commented out of autostart.sh and put test.py into /root/Python.  
Then anyone who wants to run a python program at startup can use test.py as a base.

What do you think?

Dave
