如何在输入行中输入文本:如何在命令行中询问用户输入,同时提供默认'回答用户可以编辑或删除?

时间:2015-05-12 14:31:00

标签: python python-3.x

我正在创建一个Python脚本,要求输入命令行。用户可以编辑文件的一部分。我可以要求提供新信息并在文件中覆盖它,没问题。但我宁愿将文件的编辑部分放在命令行中,因此不必完全输入。这可能吗?

文件:

1|This file
2|is not empty

示例:

>>>edit line 2
Fetching line 2
Edit the line then hit enter
>>>is not empty                  #This is written here by the script, not by the user

然后可以改为

>>>is not full either
Edited file

该文件已更改为:

1|This file
2|is not full either

我希望它能清楚我要完成的任务。

已经说过{p> This问题可以回答我的问题,它确实在一定程度上。当我使用readline运行Linux时,它会这样做。但是,我不是。我使用的是Windows而我没有使用readline。我想只使用标准库。
该问题还提供了Windows的答案。但是,我得ImportError win32console,可能是因为提到的问题不是关于Python3.4,而是我的问题。 另外,我想知道这是否可能使用标准库,而不是外部库。

4 个答案:

答案 0 :(得分:1)

不幸的是,我不知道标准库中是否有input()类型的默认值。

有一个外部解决方案 - 使用this answer中提到的win32console。然而,就我所见,它有两个陷阱。 首先,导入捆绑在包pywin32中。所以你会使用pip install pywin32,但它不起作用,因为第二个陷阱:有关pypi包的信息已经过时,它说包与Python 3.4不兼容。

但事实上,它可以工作!您应该按照pypi项目页面上显示的“下载URL”(即https://sourceforge.net/projects/pywin32/files/pywin32/)并安装最新版本。我刚为Py3​​.4安装了build 219,因为我自己也使用这个Python版本。在页面安装程序上提供了几个适用于32位和64位Windows的Python版本。

另外,我已经调整了上面链接的SO代码的代码,以便在Python 3中工作:

import win32console

_stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)

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

    _stdin.WriteConsoleInput(keys)
    return input(prompt)

if __name__ == '__main__':
    name = input_def('Folder name: ', 'it works!!!')
    print()
    print(name)

这适用于我的Windows机器......如果这对你的机器不起作用,你能提供错误信息吗?

答案 1 :(得分:1)

我写过一个行编辑器,希望能够满足您的需求。但这是一个快速而肮脏的黑客。它仅适用于Windows,在Windows 10上使用CPython 3.6.5编写,因此其使用可能有限。它已经在代码页1252(ANSI Latin 1;西欧(Windows))和代码页65001(utf-8)上进行了测试。由于没有速度优化,它非常基本且有点迟缓。 (我应该用C重写它,但我没有时间。)它几乎没有经过测试和记录不足。

import msvcrt
import os
import sys

if os.name != 'nt':
    raise NotImplementedError('This module works only on MS Windows!')

CTRL_00         = 0
CTRL_E0         = 224
KEY_BACKSPACE   = 8
KEY_DELETE      = 83                                            # CTRL
KEY_END         = 79                                            # CTRL
KEY_ESC         = 27
KEY_HOME        = 71                                            # CTRL
KEY_INSERT      = 82                                            # CTRL
KEY_LEFT        = 75                                            # CTRL
KEY_RETURN      = 13
KEY_RIGHT       = 77                                            # CTRL

flush = sys.stdout.flush
write = sys.stdout.write

mode    = ('[OVR]> ', '[INS]> ')                                # overwrite, insert
prefix  = len(mode[0])

def _update_line(insert, source, length, line, target):
    """Write a new line and position the cursor.
    source: previous cursor position
    length: old line length
    line:   edited line
    target: next cursor position
    """
    write('\b' * source)                                        # set cursor to start of line
    write(' ' * length)                                         # erase old line
    write('\b' * length)                                        # again, set cursor to start of line
    write(mode[insert] + line[prefix:])                         # write updated line
    write('\b' * (len(line) - target))                          # set cursor to new position
    flush()                                                     # write buffer to screen

def mswin_line_edit(default_string, insert=True):
    """Edit a MS Windows CLI line."""

    insert = insert
    line = mode[insert] + default_string
    count = len(line)
    before = line[:count]
    after = line[count:]
    print(line, end='', flush=True)
    cursor = count

    while True:
        key = msvcrt.getwch()
        num = ord(key)
        if num == KEY_ESC:                                      # abort edit
            return default_string
        if num == KEY_RETURN:                                   # finish edit
            return line
        if num == KEY_BACKSPACE:                                # delete character before cursor
            if cursor > prefix:
                before = line[:cursor - 1]
                after = line[cursor:]
                line = before + after
                _update_line(insert, cursor, count, line, cursor - 1)
                cursor -= 1
                count = len(line)
        elif num == CTRL_E0 or num == CTRL_00:                  # CTRL
            ctrl = ord(msvcrt.getwch())
            if ctrl == KEY_END:                                     # set cursor after last character
                if cursor < count:
                    before = line
                    after = ''
                    _update_line(insert, cursor, count, line, count)
                    cursor = count
            elif ctrl == KEY_HOME:                                  # set cursor before first character
                if cursor > prefix:
                    before = ''
                    after = line
                    _update_line(insert, cursor, count, line, prefix)
                    cursor = prefix
            elif ctrl == KEY_LEFT:                                  # move cursor 1 character to the left
                if cursor > prefix:
                    before = line[:cursor]
                    after = line[cursor:]
                    _update_line(insert, cursor, count, line, cursor - 1)
                    cursor -= 1
            elif ctrl == KEY_RIGHT:                                 # move cursor 1 character to the right
                if cursor < count:
                    before = line[:cursor]
                    after = line[cursor:]
                    _update_line(insert, cursor, count, line, cursor + 1)
                    cursor += 1
            elif ctrl == KEY_DELETE:                                # delete character after cursor
                if cursor < count:
                    before = line[:cursor]
                    after = line[cursor + 1:]
                    line = before + after
                    _update_line(insert, cursor, count, line, cursor)
                    count = len(line)
            elif ctrl == KEY_INSERT:                                # switch insert/overwrite mode
                insert ^= True
                _update_line(insert, cursor, count, line, cursor)
        else:                                                   # ordinary character
            before = line[:cursor] + key
            if insert:
                after = line[cursor:]
            else:
                after = line[cursor + 1:]
            line = before + after
            _update_line(insert, cursor, count, line, cursor + 1)
            cursor += 1
            count = len(line)

if __name__ == '__main__':
    test_string = input('test string: ')
    result = mswin_line_edit(test_string)
    print(f'\n{result}')

答案 2 :(得分:0)

你可以用tkinter做到这一点:

from tkinter import *
def enter():
    global commandEntry
    command = commandEntry.get()
    # Do stuff with command
    commandEntry.delete(0, END)
def edit_line(line):
    global commandEntry
    commandEntry.insert(0, line)
root = Tk()
messageVar = StringVar()
messageVar.set("Enter a command:")
message = Label(root, textvariable=messageVar)
commandEntry = Entry(root)
enterButton = Button(root, text="Enter", command=enter)
root.mainloop()

答案 3 :(得分:-1)

你应该只有2个变量:一个用于标准字符串,一个用于字符串,用户可以自行更改。 像:

str1 = 'String that is standard'
str2 = str1 #it usually will be standard string
usr = input('your text goes here')
if len(usr) != 0:
    str2 = usr
#and here goes code for writing string into file