Is the readline module not the right tool for an interactive Linux >command-line application that needs to provide command line recall and >editing to the user who's entering stuff on stdin from a tty?
In an interactive command-line Python program on Linux, I want to be
able to read a line at a time from stdin, providing command line
history and editing to the user. In C, I would use GNU readline to do
that.
Python has the readline module, which appears to be a wrapper for GNU readline. However, I've read and re-read the documenation for that
module, but I'm completely baffled. There's all sorts of stuff about
history files, but I neither need nor want a history file. Likewise tab-completion: don't want it. All the examples not only involve
history files and tab-completion but they're somehow connected to the interactive Python REPL, which is also completely off-base for my use
case.
Is the readline module not the right tool for an interactive Linux command-line application that needs to provide command line recall and editing to the user who's entering stuff on stdin from a tty?
In an interactive command-line Python program on Linux, I want to be
able to read a line at a time from stdin, providing command line
history and editing to the user. In C, I would use GNU readline to do
that.
Python has the readline module, which appears to be a wrapper for GNU readline. However, I've read and re-read the documenation for that
module, but I'm completely baffled.
Not sure about the history file, and I would assume that if you don't configure one, history is simply lost when you restart. But with tab completion, unless you need to be able to input a tab character, it
should be safe to ignore the feature and leave it at the defaults.
What's really weird about the docs is that when it is described it
doesn't even _mention_ that it provides command-line recall and
editing:
It just talks about manipulating history files and about
tab-completion of Python identfiers. The last sentence mentions that settings affect both the REPL prompt and the prompts offered by the
built-in input() function.
On 2023-03-09, Chris Angelico <rosuav@gmail.com> wrote:[...]
Not sure about the history file, and I would assume that if you don't
configure one, history is simply lost when you restart. But with tab
completion, unless you need to be able to input a tab character, it
should be safe to ignore the feature and leave it at the defaults.
Indeed, that seems to be how it works (though I never found that
stated anywhere in the docs).
What's really weird about the docs is that when it is described it
doesn't even _mention_ that it provides command-line recall and
editing:
It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
I think this might be the common case of a module which wraps another library: there's a tension between describing everything in pointless
detail and the trite "we're just shimming this library, go read its
docs".
You call the input() built-in.
Ah. That's not overtly stated? [...reads...] Ah, there it is in the last sentence of the opening paragraph. Not quite as in-your-face as I'd have liked it. That paragraph could do with being a bullet list of use cases.
On 2023-03-09, Cameron Simpson <cs@cskk.id.au> wrote:
[...]
It finally dawned on me after seeing an example I found elsewhere that >>you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
Ah. That's not overtly stated? [...reads...] Ah, there it is in the last sentence of the opening paragraph. Not quite as in-your-face as I'd have liked it.
What threw me off the track for a while was that the sentence to which
you refer says it affects the "prompts offered by input()". In my head,
that means it changes the string that's printed on stdout before stuff
is read from stdin. That's different that affecting the handling of
user input read by input().
It doesn't actually change anything about the prompts provided by
input(). It changes the handling of the user input by input().
I guess I read it too literally. I must spend too much time with
computers.
[...]
It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
Ah. That's not overtly stated? [...reads...] Ah, there it is in the last sentence of the opening paragraph. Not quite as in-your-face as I'd have liked it.
That paragraph could do with being a bullet list of use cases.
On 2023-03-09, Cameron Simpson <cs@cskk.id.au> wrote:
[...]
It finally dawned on me after seeing an example I found elsewhere that >>>you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
Ah. That's not overtly stated? [...reads...] Ah, there it is in the last
sentence of the opening paragraph. Not quite as in-your-face as I'd have
liked it.
What threw me off the track for a while was that the sentence to which
you refer says it affects the "prompts offered by input()". In my head,
that means it changes the string that's printed on stdout before stuff
is read from stdin. That's different that affecting the handling of
user input read by input().
It doesn't actually change anything about the prompts provided by
input(). It changes the handling of the user input by input().
I guess I read it too literally. I must spend too much time with
computers.
Yeesh. What's _really_ embarassing is that I just stumbled across a
small test program with which I had apparently figured this out 10-12
years ago. Must be about time to retire...
Yeesh. What's _really_ embarassing is that I just stumbled across a
small test program with which I had apparently figured this out 10-12
years ago. Must be about time to retire...
Having a module modify the behavior of a built-in makes me cringe.
On 2023-03-09 at 15:02:53 -0800,
Grant Edwards <grant.b.edwards@gmail.com> wrote:
Yeesh. What's _really_ embarassing is that I just stumbled across a
small test program with which I had apparently figured this out 10-12
years ago. Must be about time to retire...
Retiring doesn't help. :-)
I retired almost five years ago, and I just (within the past few days) (re)discovered a command line parsing library I'd written about a year
and a half ago (i.e., after I retired).
On Fri, 10 Mar 2023 at 10:04, Grant Edwards <grant.b.edwards@gmail.com> wrote:
Yeesh. What's _really_ embarassing is that I just stumbled across a
small test program with which I had apparently figured this out
10-12 years ago. Must be about time to retire...
You expect yourself to remember test programs you wrote a decade
ago?? I've forgotten full-on projects from that far back!
Though, congrats on being able to stumble across it. That's quite
something.
It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
Having a module modify the behavior of a built-in makes me cringe.
import readline
print("Pseudo-prompt: ", end="")
msg1 = input()
msg2 = input("Actual prompt: ")
print(repr(msg1))
print(repr(msg2))
At each of the prompts, type a bit of text, then backspace it all the
way. The actual prompt will remain, but the pseudo-prompt will get
cleared off. There'll be other small differences too.
On 10/03/23 10:08 am, Grant Edwards wrote:
It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.
You call the input() built-in.
Having a module modify the behavior of a built-in makes me cringe.
Importing the module is not modifying the built-in.
If your Python has been compiled with gnu readline support,
input() *already* provides recall and editing facilities.
You only need to import the readline module if you want to
change the configuration.
Yes, it would be helpful if the docs for the readline module
explained this. At present they seem to assume that you already
know what the readline module is for and just want a summary
of the API.
It *is* mentioned briefly in the docs for input(), but again
somebody wanting line editing functionality wouldn't necessarily
think of looking there.
I think this might be the common case of a module which wraps another
library
When a computer dies, I
generally just cp -a (or rsync -a) $HOME to a new one.
That's not how it acts for me. I have to "import readline" to get
command line recall and editing.
On 10/03/23 1:46 pm, Grant Edwards wrote:
That's not how it acts for me. I have to "import readline" to get
command line recall and editing.
Maybe this has changed? Or is platform dependent?
With Python 3.8 on MacOSX I can use up arrow with input()
to recall stuff I've typed before, without having to
import anything.
Traditional retirement: Work till you're 60 or 65 or whatever, then
society pats you on the head, calls you a "senior citizen", and lets
you go and be idle till you die (which might be prematurely soon).
Direction-change retirement: Work till you can afford to zero out your income, then finally do what you've always wanted to do, but never had
time because you spent so much of it earning money.
Tell-the-next-generation: Work till you know so much that you're
infinitely valuable, then spend the rest of your life empowering the
next group of amazing people. See for instance: NASA.
Programmer retirement: At an early age, learn how to wield PHENOMENAL
COSMIC POWER, and spend the next X years in an itty bitty working
space, earning money. Eventually, upgrade to better living/working
space. Eventually, downgrade to a small wooden box six feet below the
ground. Never once relinquish the power. Never once abandon that
feeling of mastery.
We're not really an industry that has a concept of retirement.
On 2023-03-10 at 12:57:48 +1100,
Chris Angelico <rosuav@gmail.com> wrote:
On Fri, 10 Mar 2023 at 12:56, Greg Ewing via Python-list
<python-list@python.org> wrote:
On 10/03/23 1:46 pm, Grant Edwards wrote:
That's not how it acts for me. I have to "import readline" to get
command line recall and editing.
Maybe this has changed? Or is platform dependent?
With Python 3.8 on MacOSX I can use up arrow with input()
to recall stuff I've typed before, without having to
import anything.
import sys; "readline" in sys.modules
Is it? Might be that something's pre-importing it.
My ~/.pythonrc contains the following:
import readline
import rlcompleter
readline.parse_and_bind( 'tab: complete' )
IIRC, that's been there "forever," certainly back into Python2, and
probably back into Python1. On my Arch Linux system Python 3.10.9, I
get readline behavior with or without those lines.
On Fri, 10 Mar 2023 at 12:56, Greg Ewing via Python-list <python-list@python.org> wrote:
On 10/03/23 1:46 pm, Grant Edwards wrote:
That's not how it acts for me. I have to "import readline" to get
command line recall and editing.
Maybe this has changed? Or is platform dependent?
With Python 3.8 on MacOSX I can use up arrow with input()
to recall stuff I've typed before, without having to
import anything.
import sys; "readline" in sys.modules
Is it? Might be that something's pre-importing it.
On 2023-03-10, 2QdxY4RzWzUUiLuE@potatochowder.com <2QdxY4RzWzUUiLuE@potatochowder.com> wrote:
If you run this application from the command line, you get command
recall and editing when entering strings at the "cmd:" prompt?
#!/usr/bin/python
while True:
try:
line = input('cmd: ')
except EOFError:
print()
break
print('You entered "%s"' % line)
My ~/.pythonrc contains the following:
import readline
import rlcompleter
readline.parse_and_bind( 'tab: complete' )
import sys; "readline" in sys.modules
Is it?
I was with you until that part of the small wooden box. :-)
We're not really an industry that has a concept of retirement.
Which is why I'm still here (on this mailing list, and a handful of
others like it).
I would say, “No, readline is not the right tool.”
cmd.Cmd is: https://docs.python.org/3/library/cmd.html. I have a
couple of cmd.Cmd modules, one of which I use daily and the other
weekly.
I would say, No, readline is not the right tool.cmd.html__;!!Cn_UX_p3!iH9PMR4wNfv3oBLWR_W46RY8KUzLVxsA_XRv2RJk6Td_ND59EaBvcJ58-Crx2PReX-ELMx7IEMAQ1YfpIt7xmHBGs8a1$> . I have a
cmd.Cmd is: https://urldefense.com/v3/__https://docs.python.org/3/library/cmd.html__;!!Cn_UX_p3!iH9PMR4wNfv3oBLWR_W46RY8KUzLVxsA_XRv2RJk6Td_ND59EaBvcJ58-Crx2PReX-ELMx7IEMAQ1YfpIt7xmHBGs8a1$<https://urldefense.com/v3/__https:/docs.python.org/3/library/
couple of cmd.Cmd modules, one of which I use daily and the other
weekly.
On our Linux systems, I can up-arrow to go back to prior commands
and use the left and right arrows to navigate a line. The
functionality may be provided internally by readline. I’ve never had
to dig into it because it meets my needs out of the box.
On 10/03/23 4:00 pm, 2QdxY4RzWzUUiLuE@potatochowder.com wrote:
My ~/.pythonrc contains the following:
import readline
import rlcompleter
readline.parse_and_bind( 'tab: complete' )
I don't have a ~/.pythonrc, so that's not what's doing it
for me.
On 2023-03-10, Weatherby,Gerard <gweatherby@uchc.edu> wrote:
I'll have to remember that one. It doesn't really fit my current use
case, but there are others where it would work nicely.
However, cmd.Cmd does not provide command recall and
editing. According to the page above, that's provided by the readline
module
On 2023-03-10, Weatherby,Gerard <gweatherby@uchc.edu> wrote:
On our Linux systems, I can up-arrow to go back to prior commands
and use the left and right arrows to navigate a line. The
functionality may be provided internally by readline. I’ve never had
to dig into it because it meets my needs out of the box.
Apparently the cmd.Cmd docs are wrong. It says:
If the readline module is loaded, input will automatically
inherit bash-like history-list editing (e.g. Control-P scrolls
back to the last command, Control-N forward to the next one,
Control-F moves the cursor to the right non-destructively,
Control-B moves the cursor to the left non-destructively, etc.).
On my Python 3.10.10 Linux system, cmd.Com itself is importing the
readline module unconditionally when I call cmdloop(). There's no 'if'
about it.
On 10Mar2023 09:12, Grant Edwards <grant.b.edwards@gmail.com> wrote:
On 2023-03-10, Weatherby,Gerard <gweatherby@uchc.edu> wrote:
On our Linux systems, I can up-arrow to go back to prior commands
and use the left and right arrows to navigate a line. The
functionality may be provided internally by readline. I’ve never had
to dig into it because it meets my needs out of the box.
Apparently the cmd.Cmd docs are wrong. It says:
If the readline module is loaded, input will automatically
inherit bash-like history-list editing (e.g. Control-P scrolls
back to the last command, Control-N forward to the next one,
Control-F moves the cursor to the right non-destructively,
Control-B moves the cursor to the left non-destructively, etc.).
On my Python 3.10.10 Linux system, cmd.Com itself is importing the
readline module unconditionally when I call cmdloop(). There's no 'if' >>about it.
I was wondering about that myself, whether this is an accident of
phrasing. It doesn't say "is imported", so maybe the author was thinking
"if readline's part of the install" here.
On 2023-03-10, Weatherby,Gerard <gweatherby@uchc.edu> wrote:
On our Linux systems, I can up-arrow to go back to prior commands
and use the left and right arrows to navigate a line. The
functionality may be provided internally by readline. Ive never had
to dig into it because it meets my needs out of the box.
Apparently the cmd.Cmd docs are wrong. It says:
If the readline module is loaded, input will automatically
inherit bash-like history-list editing (e.g. Control-P scrolls
back to the last command, Control-N forward to the next one,
Control-F moves the cursor to the right non-destructively,
Control-B moves the cursor to the left non-destructively, etc.).
On my Python 3.10.10 Linux system, cmd.Com itself is importing the
readline module unconditionally when I call cmdloop(). There's no 'if'
about it.
This is the implementation of cmd.Cmd (Python 3.9). As you can see in cmdloop(), the import is already wrapped, and the readline feature can be turned off explicitly by passing None to the completekey in the constructor.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (2 / 14) |
Uptime: | 02:05:35 |
Calls: | 10,385 |
Calls today: | 2 |
Files: | 14,057 |
Messages: | 6,416,581 |