I want to run a python program that polls the keyboard on startup/login to my raspberry pi.

Previous attempts included cron jobs (failed due to lack of stdin or stdout).

rc.local also failed as it has no stdin (it got stuck in a perpetual loop - now that was fun to escape)

Hence I've arrived at placing my command into the .profile, and this appears to work well! The program functions exactly as intended when the Pi is turned on but...

When I then try to launch the GUI by startx, the screen turns black and completely fails to launch. It seems to be something to do with the Ppython program, because when I remove it from the bash .profile, it all functions fine.

Any help would be massively appreciated!


I created a script that also output to LED's (a simple Red-Yellow-Green sequence) and it appears that .profile is execute again when startx is run? If so why?

Below is my .profile code, and then my python program; the significance of the python script is (I believe) that it runs a threaded perpetual loop that is terminated by stdin/keyboard

.profile lines

echo "About to run keyboard polling"; sleep 3
python /home/pi/poll_keyboard.py


import thread
import time
def input_thread(L):
    key = raw_input()
    thread.exit() #Should close thread at end
def do_print():
    L = []
    thread.start_new_thread(input_thread, (L,))
    i = 0
    while True:
        print "Hello World %d" % i
        if L: #If anything has been detected
        i += 1
    return L
key = do_print()
print "Key press detected: %s. Exiting in 2" % key
  • I dont want to share the keyboard per se - I want to run my python script in the CLI on bootup, and then just to load the GUI. The issue (I think) is that .profile runs again - and because the GUI 'takes' the keyboard, it never completes
    – davidhood2
    Commented Oct 20, 2016 at 9:47
  • Mmm. I've overwritten the image for my Pi (long since) so I can't check easily, but I didn't think the GUI was loaded from .profile. I would have expected it to be started from the boot process. Commented Oct 20, 2016 at 9:51
  • 1
    I'm not sure this is unique to a Pi - I suspect this would occur if you had any linux machine from which you could load a GUI using startx? (I have no linux machine so I'm unable to test this out). If it helps, my Pi is configured to login straight to command line and not directly to the GUI
    – davidhood2
    Commented Oct 20, 2016 at 9:54

1 Answer 1


The situation here is that you start at the command line and then call startx when you're ready. Empirically you believe that the GUI tries to re-execute the .profile and the python script can't exit so the GUI hangs.

One solution that might be worth trying is to set an environment variable to ensure your code is run only once:

# This is .profile
if test -z "$DONE_PROFILE" -o "X$DONE_PROFILE" != "X${USER:-unknown}"
    # Protected code here will be called only once
    echo "About to run keyboard polling"; sleep 3
    python /home/pi/poll_keyboard.py

    export DONE_PROFILE="${USER:-unknown}"

Another option is to call the code only if stdin is attached to a terminal:

# This is .profile
if test -t 0 -a -t 1
    # Protected code here will be called only if stdin and stdout is a tty
    echo "About to run keyboard polling"; sleep 3
    python /home/pi/poll_keyboard.py

This second suggestion is probably safer because it will then handle programs that log in remotely to run a service (such as rsync or scp).

You could even merge the two so that the code is considered only once, and then only executed if stdin and stdout are connected to a terminal. (Just nest the if...fi statements.)

I've been asked to explain the test condition that protects the code in the first example.

if test -z "$DONE_PROFILE" -o "X$DONE_PROFILE" != "X${USER:-unknown}"

This can be written in English as "If $DONE_PROFILE is empty Or $DONE_PROFILE does not match $USER...".

The ${USER:-unknown} construct substitutes unknown if $USER is empty or unset.

Putting X in front of both sides of the != expression is probably unnecessary in this instance, but it comes from a defensive scripting approach. Consider a variable $A that has the value -z, and another variable $B with the value apple. In some shells, writing test "$A" != "$B" would expand as test -z != apple which is syntactically invalid. Prefixing both sides with X would result in an expansion of test X-z != Xapple which is syntactically safe.

  • Amazing - works perfectly! I'm not as familiar with shell as I should be though so would be very grateful for some commenting/explanation of $DONE_PROFILE" -o "X$DONE_PROFILE" != "X${USER:-unknown} but otherwise thank you very much!
    – davidhood2
    Commented Oct 20, 2016 at 15:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .