Nick Humrich
Nick Humrich

Reputation: 15755

python Get input without ctrl character (^)

I am trying to get user input into python. However if a user uses a key such as [Home] or Ctrl+A or Ctrl+k (typical shell commands) they get a character representing that key rather than the expected behaviour.

I currently have:

data = input("Enter your data here: ").strip()

However if the user uses the Ctrl+A to go to beginning of line, they instead get a ^A character printed on the screen as part of their input.

Is there a way for me to get input in a way that would allow the user to use bash key combos like Ctrl+A?

Upvotes: 2

Views: 156

Answers (1)

abarnert
abarnert

Reputation: 365717

The short version is to just add import readline to the top of your script, and it will magically work.

More specifically, the readline library provides a wrapper around libreadline, which is the same library that lets your bash shell, or the Python interactive interpreter, for that matter, do fancy input editing.

So, you could use readline directly. If you want to do anything fancy, you should read the docs, and also see rlcompleter.

But for simple cases like this: by default, just importing readline will (in effect) patch input for you,* and that's all you need.

So, assuming the user (and his distro) are using default settings, they will be able to use the same emacs-style keystrokes they use in bash. (And, if they've changed the settings, presumably they want to be able to use those settings in your program, not just in bash.)


The only problem is that this only works if libreadline was present when Python was built:

  • On most Linux and *BSD systems, this isn't an issue.**
  • On OS X, it would be an issue, but Python provides a workaround that uses BSD libedit instead, which Apple includes.***
  • On Windows, if you're running inside a normal cmd.exe "DOS box", you automatically get DOS-style line editing, and can't get anything better... but fortunately, Windows users don't know what they're missing. :)

* If you're wondering how it works under the covers, the code underlying input is cleverly designed to be hooked by both readline and IDLE, in a way that's flexible enough that you can even do nifty things like integrate it into an asyncio event loop. So, readline doesn't really patch input; instead, it just registers a hook. Which is cool, and worth reading the source for, but it's not relevant to your question.

** And if it is, there's not much you can do about it except just install libreadline and rebuild Python. On *BSD, I guess you could configure Python to build the OS X libedit wrapper, but I don't know why you'd bother.

*** If you're using a pre-built Python from Apple or (until recently) python.org, you'll be using this workaround. Most apps and most users won't be affected by the difference, but there can be some annoyances with it. The way to force a solution to those annoyances is to depend on a newer version of readline off PyPI, which will fail if your users haven't installed libreadline.

Upvotes: 2

Related Questions