Python3: readline equavalent in select.select ()

In a Python script, programmers can import readline, which then provides advanced input options () (readline has many other uses). I want to use select.select () in my scripts instead of input (), because I like the timeout function. However, when readline is imported, I cannot use the functions that input () receives with readline. An example of the “advanced functions” that I mean by is to press the top key and see the previous entry or use the left and right arrow keys to move the built-in cursor to make changes to the input.

Question: How can I do select.select () of the GNU-readline function? Is it possible?

EDIT: Just in case, one of you is interested in what I'm trying to accomplish, I created a terminal chatbot (sort of like Alicebot). I want the bot to get bored and do something else if the bit did not receive any input within a set amount of time. ( https://launchpad.net/neobot )

+4
source share
2 answers

You can accomplish this using the readline.set_pre_input_hook ([function]) mechanism of the readline module.

Here is an example that time intervals after 10 seconds without input — not implemented — are a mechanism to silence an alarm if input is provided.

- , . .

, . python2.7, python3 - .

, - input_loop(), , .

readline.c Python .

#!/usr/bin/python

import readline
import logging
import signal
import os

LOG_FILENAME = '/tmp/completer.log'
HISTORY_FILENAME = '/tmp/completer.hist'

logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG,)

class YouAreTooSlow(Exception): pass


def get_history_items():
    return [ readline.get_history_item(i)
             for i in xrange(1, readline.get_current_history_length() + 1)
             ]

class HistoryCompleter(object):

    def __init__(self):
        self.matches = []
        return

    def complete(self, text, state):
        response = None
        if state == 0:
            history_values = get_history_items()
            logging.debug('history: %s', history_values)
            if text:
                self.matches = sorted(h 
                                      for h in history_values 
                                      if h and h.startswith(text))
            else:
                self.matches = []
            logging.debug('matches: %s', self.matches)
        try:
            response = self.matches[state]
        except IndexError:
            response = None
        logging.debug('complete(%s, %s) => %s', 
                      repr(text), state, repr(response))
        return response

def input_loop():
    if os.path.exists(HISTORY_FILENAME):
        readline.read_history_file(HISTORY_FILENAME)
    print 'Max history file length:', readline.get_history_length()
    print 'Startup history:', get_history_items()
    try:
        while True:
            line = raw_input('Prompt ("stop" to quit): ')
            if line == 'stop':
                break
            if line:
                print 'Adding "%s" to the history' % line
    finally:
        print 'Final history:', get_history_items()
        readline.write_history_file(HISTORY_FILENAME)

# Register our completer function

def slow_handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise YouAreTooSlow()

def pre_input_hook():
    signal.signal(signal.SIGALRM, slow_handler)
    signal.alarm(10)

readline.set_pre_input_hook(pre_input_hook)
readline.set_completer(HistoryCompleter().complete)

# Use the tab key for completion
readline.parse_and_bind('tab: complete')

# Prompt the user for text
input_loop()
+3

, readline ().

readline(). / / , , () . , readline " " . , .

, , Python. , , POC, CTypes. , , , .

-1

All Articles