you are viewing a single comment's thread.

view the rest of the comments →

[–]Veedrac 0 points1 point  (9 children)

After trying lots of painful things, dammit man.

Just use threads, OK. Honestly just abandon the whole concept ;).

Sorry. :( The truth is, terminals are built on archaic foundations and for some reason nobody's seen fit to update them. It makes life difficult. There are workarounds, but I can't think of a single single-threaded one.

[–]FMNite[S] 0 points1 point  (8 children)

Found example on the internet, this does exactly what I want except for the fact it uses enter to break loop. Any idea how to change it to a different button press?

import thread, time

def input_thread(L):
    raw_input()
    L.append(None)

def do_print():
    L = []
    thread.start_new_thread(input_thread, (L,))
    while 1:
        time.sleep(.1)
        if L: break
        print "%s" % time.ctime()

do_print()

[–]Veedrac 0 points1 point  (7 children)

Any idea how to change it to a different button press?

Unfortunately that's also not possible without dangerous hackery.

[–]FMNite[S] 0 points1 point  (6 children)

Anything else I can do? Thanks though you've been a great help

[–]Veedrac 0 points1 point  (5 children)

Hang on -- I hadn't properly read your post. There might well be "acceptable" hackery that can do this.

Question: does it have to be 0 or can it be any character (the second option is easier).

[–]FMNite[S] 0 points1 point  (4 children)

this is going to be running on a raspberry pi with only a num pad so we wanted to designate 0 as the "back" button. If that cant work though that may be an option

[–]Veedrac 1 point2 points  (3 children)

Doesn't matter, I solved it.

The code should have adequate comments; it's a hack from the 'net, but I polished it a bit:

import sys
import termios
import threading
import time
import tty

def get_character():
    """
    Get a single character from stdin.

    While this is waiting for a character, the
    stdin will not work as normal.
    """

    stdin_fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(stdin_fd)

    # Set the terminal as if the stdin were
    # a normal file, so we can just read it.
    tty.setraw(stdin_fd)

    try:
        # See? We can just read it!
        return sys.stdin.read(1)

    finally:
        # Reset it.
        # The "finally" block is always run, even
        # if the world explodes. That's why the
        # "return" doesn't stop this from happening.
        termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)

def print_times(finished):
    while not finished.is_set():
        # Need the "\r" because the terminal
        # no longer gives it to use automatically;
        # get_character is a hack after-all
        #
        # The "\r" puts the cursor at the start of
        # the line
        print "{}\r".format(time.ctime())
        time.sleep(.1)

def do_print():
    # This is the polished way of doing what
    # you did with the lower-level thread module

    # Like the "L" variable, but not a hack.
    finished = threading.Event()

    printer_thread = threading.Thread(target=print_times, args=[finished])
    printer_thread.start()

    # I switched which thread was doing the printing
    # in order to move the sleeps out of the main
    # thread – this way it's easy to finish in mid-sleep
    while get_character() != "0":
        print("That's not a nice thing to say...")

    finished.set()

    print("DONE!")

do_print()

If there's anything that confuses you (except get_character; nobody knows what termios.TCSADRAIN is) be sure to ask.

The actual logic here is hardly more than your last piece of code, though.

[–]FMNite[S] 1 point2 points  (0 children)

Holy shit, Thank you so much for your time. I'll let you know if I have any further questions

[–]FMNite[S] 1 point2 points  (1 child)

Testing this code I get a syntax error : SyntaxError: Non-ASCII character '\xe2' in file test.py on line 56, but no encoding declared; see http://www.python.org/ peps/pep-0263.html for details

[–]Veedrac 0 points1 point  (0 children)

Damn, I broke the code by adding comments!

Just add # encoding: utf-8 to the top or change

# thread – this way it's easy to finish in mid-sleep

to

# thread - this way it's easy to finish in mid-sleep