可以在 Python 输入上显示编辑的默认值吗?

Python 是否可能接受这样的输入:

Folder name: Download

但是用户并没有输入“下载”,它已经作为一个初始值存在了。如果用户想编辑它作为“下载”所有他需要做的就是添加一个“ s”,然后按回车键。

使用普通输入命令:

folder=input('Folder name: ')

我只能得到一个空白提示:

Folder name:

有没有什么简单的方法能解决我所不知道的问题?

40640 次浏览

我猜你是指从命令行。我从未见过命令行提示符的初始值,它们通常是这样的形式:

Folder [default] :

其代码简单如下:

res = raw_input('Folder [default] : ')
res = res or 'default'

或者,您可以尝试使用 Python 中的 诅咒模块执行某些操作。

标准库函数 input()raw_input()没有这个功能。如果你正在使用 Linux,你可以使用 readline模块来定义一个输入函数,它使用一个预填充值和高级行编辑:

import readline


def rlinput(prompt, prefill=''):
readline.set_startup_hook(lambda: readline.insert_text(prefill))
try:
return input(prompt)  # or raw_input in Python 2
finally:
readline.set_startup_hook()

如果您这样做,用户将不得不删除现有的单词。如果用户点击“返回”,那么提供一个默认值怎么样?

>>> default_folder = "My Documents"
>>> try: folder = input("folder name [%s]:" %default_folder)
... except SyntaxError: folder = default_folder

我认为最好的(最简单和最便携的)解决方案是@rlotun 和@Stephen 回答的结合:

default = '/default/path/'
dir = raw_input('Folder [%s]' % default)
dir = dir or default

这个可以在窗户上使用。

import win32console


_stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)


def input_def(prompt, default=''):
keys = []
for c in unicode(default):
evt = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
evt.Char = c
evt.RepeatCount = 1
evt.KeyDown = True
keys.append(evt)


_stdin.WriteConsoleInput(keys)
return raw_input(prompt)


if __name__ == '__main__':
name = input_def('Folder name: ')
print
print name

不是最好的方法,但为了分享..。 您可以使用 Javascript 来获取 IPython Notebook 中的所有类型的输入。

from IPython.display import HTML
newvar = ""
htm = """
<input id="inptval" style="width:60%;" type="text" value="This is an editable default value.">
<button onclick="set_value()" style="width:20%;">OK</button>


<script type="text/Javascript">
function set_value(){
var input_value = document.getElementById('inptval').value;
var command = "newvar = '" + input_value + "'";
var kernel = IPython.notebook.kernel;
kernel.execute(command);
}
</script>
"""
HTML(htm)

在下一个单元格中,可以使用新变量:

print newvar

这不是一个很好的答案,但它是一个工作周围的窗口。不管我怎么努力,我都无法让 Readline 或 pyReadline 在我的 Windows10计算机上使用 Python Ver 3.5。所以我写了这个。这不是世界上最好的代码,因为我只用了 Python 3个月。但是很有效。

    import os


def note_input(defaultvalue):
#Create a textfile
txtfile = open("txtfile.txt", "w")
#
# populate it with the default value
txtfile.write(defaultvalue)
txtfile.close()
#
# call Notepad
os.system("notepad.exe txtfile.txt")
# input("Just holding until notepad is close : ") (did not need this line)
#
# get the Value Entered/Changed in Notepad
txtfile = open("txtfile.txt", "r")
func_value = txtfile.read()
txtfile.close()
return func_value
# END DEF

记事本停止程序运行,直到它被关闭,所以它下面的 input ()行是不需要的。一旦记事本第一次打开,放在我想要它在屏幕上的地方,它就像一个弹出式输入窗口。我假设您可以使用任何文本编辑器,如记事本 + + 或 Scripe 或代码编写器等。

我们可以使用 Tkinter 和 StringVar 来完成这项工作。限制是输入是通过 Tkinter 窗口进行的。

from tkinter import Tk, LEFT, BOTH, StringVar
from tkinter.ttk import Entry, Frame




class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()


def initUI(self):
self.parent.title("Entry")
self.pack(fill=BOTH, expand=1)
self.contents = StringVar()
# give the StringVar a default value
self.contents.set('test')
self.entry = Entry(self)
self.entry.pack(side=LEFT, padx=15)
self.entry["textvariable"] = self.contents
self.entry.bind('<Key-Return>', self.on_changed)


def on_changed(self, event):
print('contents: {}'.format(self.contents.get()))
return True




def main():
root = Tk()
ex = Example(root)
root.geometry("250x100+300+300")
root.mainloop()




if __name__ == '__main__':
main()

我想建议使用剪贴板来解决这个问题。将剪贴板粘贴到输入行,根据需要进行编辑,按回车键。变量 clpstack 用于保护现有剪贴板内容。此代码适用于 Windows。Linux 可以使用导入剪贴板。

import pyperclip as clp
clpstack=clp.paste()
clp.copy("192.168.4.1")
HOST = input("Enter telnet host: ")
clp.copy(clpstack)

我喜欢这个,可以装在窗户上

def inputWdefault(prompt, default):
bck = chr(8) * len(default)
ret = input(prompt + default + bck)
return ret or default

我终于找到了一个可以在 Windows 和 Linux 上运行的简单替代方案。本质上,我使用 Pyautogui模块来模拟用户的输入。实际上,它是这样的:

from pyautogui import typewrite


print("enter folder name: ")
typewrite("Default Value")
folder = input()

Example

警告:

  1. 理论上,用户可以通过在 typewrite结束之前按一个键在“默认”输入的中间插入字符。
  2. Pyautogui 在无头系统上是出了名的不可靠,所以一定要提供备份解决方案,以防导入失败。如果遇到 No module named 'Xlib',请尝试安装 python3-xlibpython-xlib包(或 xlib模块)。运行 ssh 也可能是个问题

一个后备实现的例子:

由于缺失的 X 服务器逻辑上只能发生在 Linux 上,这里有一个使用某事物的答案作为备用的实现:

try:
from pyautogui import typewrite
autogui = True
except (ImportError, KeyError):
import readline
autogui = False


def rlinput(prompt, prefill=''):
if autogui:
print(prompt)
typewrite(prefill)
return input()
else:
readline.set_startup_hook(lambda: readline.insert_text(prefill))
try:
return input(prompt)
finally:
readline.set_startup_hook()

我发现 PyInquirer非常有用,特别是在频繁构建交互式控制台应用程序时。提示具有默认可修改值的用户如下所示:

from PyInquirer import prompt


question = [
{
'type': 'input',
'name': 'first_name',
'message': 'Name please',
'default': 'Max'
}
]


answer = prompt(question)
print('Hello {}'.format(answer['first_name']))

我喜欢@MCO 采用的方法,所以我重构了代码。我在 X Windows 和 Microsoft Windows 10 WSL 2上使用 Microsoft Terminal 进行了测试:

def input_with_default(prompt, prefill=''):
try:
from pyautogui import typewrite
print(prompt)
typewrite(prefill)
return input()
except (ImportError, KeyError):
import readline
readline.set_startup_hook(lambda: readline.insert_text(prefill))
try:
return input(prompt)
finally:
readline.set_startup_hook()

最近遇到了这个问题。以上的答案似乎没有一个是完美无缺的。所以我做了一些研究,发现下面的解决方案是最简单的,并且适用于 Windows 和 Linux:

import keyboard


def input_with_default(prompt_, default_):
keyboard.write(default_)
return input(prompt_)


if __name__ == "__main__":
print(input_with_default("Please enter: ", "hello world"))

如果您正在编写 CLI,那么您可能需要考虑使用 python-click库来完成此任务。

你可以通过以下代码来实现你的目标:

import click


user_input = click.prompt(text="Folder name", default="Download")
print(f"{user_input=}")

如果您运行这段代码,并且什么也没有输入,那么您将得到:

$ python3 cli_code.py
Folder name [Download]:
user_input='Download'

如果您运行这段代码,并输入“ my-dir”,那么您将得到:

$ python3 cli_code.py
Folder name [Download]: my-dir
user_input='my-dir'

尝试使用“ f-string”和“ or”组合,比如:

default_name = "that_folder"


this_folder = input(f"Folder name: ({default_name}) ") or default_name
print(this_folder)

如果您没有键入文件夹名称而单击 Return,则将假定为 default _ name。