如何为raw_input设置默认的可编辑字符串?

61
我使用Python 2.7的raw_input函数从标准输入读取数据。 我想让用户修改一个默认的字符串。 代码:
i = raw_input("Please enter name:")

控制台:

Please enter name: Jack

用户应该看到Jack,但可以更改(使用回格键)为其他内容。

Please enter name:参数将作为raw_input的提示,并且该部分不应该被用户更改。


可能是 Python输入时显示默认值是否可能? 的重复问题。 - Georgy
7个回答

83
您可以这样做:
i = raw_input("Please enter name[Jack]:") or "Jack"

这样,如果用户只是按下回车键而没有输入任何内容,“i” 将被分配为“Jack”。


21
这不符合问题要求。Jack 无法编辑。 - buhtz
1
但这是提供默认输入的常见Unix模式。如果您想接受默认值,只需按回车键即可。 - chubbsondubs
8
问题不是关于“常见的Unix模式”。 - buhtz

32

使用Python2.7获取raw_input并设置默认值:

将以下内容保存到名为a.py的文件中:

import readline
def rlinput(prompt, prefill=''):
   readline.set_startup_hook(lambda: readline.insert_text(prefill))
   try:
      return raw_input(prompt)
   finally:
      readline.set_startup_hook()

default_value = "an insecticide"
stuff = rlinput("Caffeine is: ", default_value)
print("final answer: " + stuff)
运行程序后,它会停止并向用户呈现以下内容:
el@defiant ~ $ python2.7 a.py
Caffeine is: an insecticide

光标在末尾,用户按退格键直到“杀虫剂”消失,然后输入其他内容,然后按回车键:

el@defiant ~ $ python2.7 a.py
Caffeine is: water soluable

程序以以下方式结束,最终答案取决于用户输入的内容:

el@defiant ~ $ python2.7 a.py 
Caffeine is: water soluable
final answer: water soluable

等同于上面,但适用于Python3:

import readline    
def rlinput(prompt, prefill=''):
   readline.set_startup_hook(lambda: readline.insert_text(prefill))
   try:
      return input(prompt)
   finally:
      readline.set_startup_hook()

default_value = "an insecticide"
stuff = rlinput("Caffeine is: ", default_value)
print("final answer: " + stuff)

这里有更多关于发生了什么的信息:

https://dev59.com/NHE85IYBdhLWcg3w8IbK#2533142


2
这个程序在Windows上也能运行吗?还是只能在Linux上运行? - ChaimG
你真是个天才!非常感谢你! - Stepan Rogonov
1
@ChaimG:不幸的是:pip install readline会产生错误:error: this module is not meant to work on Windows - Bigue Nique

7
在dheerosaur的回答中,如果用户按Enter键选择默认值,实际上它不会被保存,因为Python认为它是一个''字符串。在dheerosaur的基础上进一步扩展。
default = "Jack"
user_input = raw_input("Please enter name: %s"%default + chr(8)*4)
if not user_input:
    user_input = default

提醒一下.. 回退键的 ASCII 值08


2
这是个不错的技巧,谢谢。但仍然不是我想要的,因为用户无法真正更改给定的默认字符串或使用箭头键进行导航。当然,可以绕过这个问题,但对于这样一个小功能来说,这有点超出范围。 - ifschleife
应该是 'chr(8)*len(default)' 吧? - nvd
1
“Jack” 只是被打印出来了,但并没有被设置为默认值。 - buhtz

6
我只是加上这段话是因为你应该编写一个简单的函数以便重复使用。这是我写的函数:
def default_input( message, defaultVal ):
    if defaultVal:
        return raw_input( "%s [%s]:" % (message,defaultVal) ) or defaultVal
    else:
        return raw_input( "%s " % (message) )

这不符合问题要求。 - buhtz
我重新阅读了这个问题,仍然认为它是有道理的。你可能需要更好地解释一下你的立场。 - chubbsondubs
1
@chubbsndubs 引用问题中的话:“但可以将其更改(退格)为其他内容”。这意味着用户应该能够编辑默认值。 - buhtz
1
你过于追求细节了。我的建议以稍微不同的方式提供了OP所请求的功能。这暗示着,如果OP可以改变他们的要求,我认为这是非常小的改变,那么这个解决方案将适用于他们。如果不能,那么答案就是你不能使用raw_input()来完成它,你可能需要考虑使用readline来实现一个非便携式的解决方案。 - chubbsondubs

5
在支持readline的平台上,您可以使用此处描述的方法:https://dev59.com/NHE85IYBdhLWcg3w8IbK#2533142 在Windows上,您可以使用msvcrt模块:
from msvcrt import getch, putch

def putstr(str):
    for c in str:
        putch(c)

def input(prompt, default=None):
    putstr(prompt)
    if default is None:
        data = []
    else:
        data = list(default)
        putstr(data)
    while True:
        c = getch()
        if c in '\r\n':
            break
        elif c == '\003': # Ctrl-C
            putstr('\r\n')
            raise KeyboardInterrupt
        elif c == '\b': # Backspace
            if data:
                putstr('\b \b') # Backspace and wipe the character cell
                data.pop()
        elif c in '\0\xe0': # Special keys
            getch()
        else:
            putch(c)
            data.append(c)
    putstr('\r\n')
    return ''.join(data)

请注意,在Windows版本中,箭头键无效。当使用时,不会发生任何事情。

2
对于使用 windows 的用户,如果安装了 gitbash/msys2 或者 cygwin,你可以通过 python 的 subprocess 使用其内置的 readline 功能。虽然这种方法有点取巧,但是效果很好,而且不需要任何第三方代码。对于个人工具而言,这种方法非常适用。
针对 Msys2 用户:如果你希望按下 ctrl+c 即可立即退出程序,则需要使用以下命令运行你的程序:winpty python program.py
import subprocess
import shlex

def inputMsysOrCygwin(prompt = "", prefilled = ""):
    """Run your program with winpty python program.py if you want ctrl+c to behave properly while in subprocess"""
    try:
        bashCmd = "read -e -p {} -i {} bash_input; printf '%s' \"$bash_input\"".format(shlex.quote(prompt), shlex.quote(prefilled))
        userInput = subprocess.check_output(["sh", "-c", bashCmd], encoding='utf-8')
        return userInput
    except FileNotFoundError:
        raise FileNotFoundError("Invalid environment: inputMsysOrCygwin can only be run from bash where 'read' is available.")

userInput = ""
try:
    #cygwin or msys2 shell
    userInput = inputMsysOrCygwin("Prompt: ", "This is default text")
except FileNotFoundError:
    #cmd or powershell context where bash and read are not available 
    userInput = input("Prompt [This is default text]: ") or "This is default text"

print("userInput={}".format(userInput))

-4
尝试这个:raw_input("请输入名称:Jack" + chr(8)*4) 退格的ASCII值是08

2
"Jack" 只是被打印出来了,但不作为默认设置。 - buhtz
@buhtz 感谢您指出。请随意编辑答案。 - dheerosaur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接