在python

时间:2016-05-28 11:59:26

标签: python cmd

在Python中,是否可以在控制台中使用input()请求用户输入,同时在提示之前打印出行中的文本? 看起来应该是这样的:

Text 1
Text 2
Text 3
Please enter something: abc

每当打印新文本时,应在前一个文本之后和input()提示符之前打印。此外,它不应该中断用户输入文本。

因此,在打印" Text 4"控制台应如下所示:

Text 1
Text 2
Text 3
Text 4
Please enter something: abc

在没有使用任何外部库的情况下,这可以在Python中完成吗?

我已经尝试过使用\ r,\ b和类似的代码以及线程。 我也知道我可能需要有一个线程打印文本,而另一个请求用户输入。

3 个答案:

答案 0 :(得分:2)

在Linux上你可以这样做:

#!/usr/bin/python

CURSOR_UP_ONE = '\x1b[1A'
ERASE_LINE = '\x1b[2K'

print('Text 1\nText 2\nText 3')

inp = ''
while inp != 'END':
    inp = raw_input('Please enter something:')
    print(CURSOR_UP_ONE + ERASE_LINE + inp)

重点在于每次将光标向上移动一行并删除行Please enter something:。然后,您可以在其位置写入输入,并在需要时再次写入有关输入的通知。

特殊字符串:

CURSOR_UP_ONEERASE_LINE是具有特殊含义的字符串。完整列表,如果您可以找到那些终端转义控制序列HERE

在Windows上使用ANSI终端转义控制序列:

在某种程度上,也可以在Windows上使用此序列。例如。这些问题涉及这个主题:

此脚本的工作流程

enter image description here enter image description here enter image description here enter image description here

答案 1 :(得分:2)

这是使用ANSI / VT100终端控制转义序列的另一种方法。

我们告诉终端仅滚动打印输出数据的终端的上部区域,以便打印输入提示的下部区域保持固定。当我们退出程序时(使用 Ctrl C ),我们需要恢复默认的滚动设置。

此程序首先清除屏幕,然后坐在一个循环中,提示用户输入一个数字n,然后以range(n)打印数字,每行一个,但延迟时间很短更容易看到发生了什么。每个范围的输出从前一个范围开始。如果用户输入非整数,则重新打印提示。导入readline模块,以便在输入提示符处提供编辑和历史记录;此模块可能并非在所有平台上都可用。

首先是Python 2版本。

''' Print text in a scrolling region of the terminal above a fixed line for input

    Written by PM 2Ring 2016.05.29

    Python 2 version
'''

from __future__ import print_function
from time import sleep
import readline

# Some ANSI/VT100 Terminal Control Escape Sequences
CSI = '\x1b['
CLEAR = CSI + '2J'
CLEAR_LINE = CSI + '2K'
SAVE_CURSOR = CSI + 's'
UNSAVE_CURSOR = CSI + 'u'

def emit(*args):
    print(*args, sep='', end='')

def set_scroll(n):
    return CSI + '0;%dr' % n

# Height of scrolling region
height = 40

GOTO_INPUT = CSI + '%d;0H' % (height + 1)

emit(CLEAR, set_scroll(height))

try:
    while True:
        #Get input
        emit(SAVE_CURSOR, GOTO_INPUT, CLEAR_LINE)
        try:
            n = int(raw_input('Number: '))
        except ValueError:
            continue
        finally:
            emit(UNSAVE_CURSOR)

        #Display some output
        for i in range(n):
            print(i)
            sleep(0.1)

except KeyboardInterrupt:
    #Disable scrolling, but leave cursor below the input row
    emit(set_scroll(0), GOTO_INPUT, '\n')

这是一个在Python 2和Python 3上运行的版本。在Python 3上运行时,此脚本调用shutil.get_terminal_size()来设置滚动区域的高度。 可以在Python 2中获取终端大小,但代码相当混乱,所以我选择了固定的高度。

我应该提一下,如果在运行时更改终端大小,则此脚本的两个版本都无法很好地应对;妥善处理是留给读者的练习。 :)

''' Print text in a scrolling region of the terminal above a fixed line for input

    Written by PM 2Ring 2016.05.29

    Python 2 / 3 version
'''

from __future__ import print_function
import sys
import readline
from time import sleep

if sys.version_info > (3,):
    # Get the (current) number of lines in the terminal
    import shutil
    height = shutil.get_terminal_size().lines - 1

    stdout_write_bytes = sys.stdout.buffer.write
else:
    height = 40
    input = raw_input
    stdout_write_bytes = sys.stdout.write


# Some ANSI/VT100 Terminal Control Escape Sequences
CSI = b'\x1b['
CLEAR = CSI + b'2J'
CLEAR_LINE = CSI + b'2K'
SAVE_CURSOR = CSI + b's'
UNSAVE_CURSOR = CSI + b'u'

GOTO_INPUT = CSI + b'%d;0H' % (height + 1)

def emit(*args):
    stdout_write_bytes(b''.join(args))

def set_scroll(n):
    return CSI + b'0;%dr' % n

emit(CLEAR, set_scroll(height))

try:
    while True:
        #Get input
        emit(SAVE_CURSOR, GOTO_INPUT, CLEAR_LINE)
        try:
            n = int(input('Number: '))
        except ValueError:
            continue
        finally:
            emit(UNSAVE_CURSOR)

        #Display some output
        for i in range(n):
            print(i)
            sleep(0.1)

except KeyboardInterrupt:
    #Disable scrolling, but leave cursor below the input row
    emit(set_scroll(0), GOTO_INPUT, b'\n')

答案 2 :(得分:1)

你可以通过这样的方式模仿你想要的东西:

import os

def clear(): os.system('cls')

screen = ""
prompt = ""

def printToScreen(s):
    global screen, prompt
    clear()
    screen += (s + '\n')
    print(screen)
    print(prompt)

def promptToScreen(p):
    global screen, prompt
    clear()
    print(screen)
    s = input(p)
    prompt = p + s
    return s

#test:

while True:
    s = promptToScreen("Enter anything -- or press 'Enter' to quit: ")
    if len(s) > 0:
        printToScreen(s)
    else:
        break

以下两个屏幕截图显示了它的工作原理:

enter image description here

然后:

enter image description here

这是一个Windows解决方案。在其他操作系统中 - 使用他们的命令清除屏幕。您可以通过编写clear()使其更具可移植性,以便根据操作系统发出不同的命令。以上几乎是概念证明。关键的想法是维护一个字符串,表示您希望终端查看的方式,然后编写自己的打印函数,修改字符串,清除终端,然后将该屏幕打印到命令提示符。除非你做了一些奇怪的事情,否则开销的数量可以忽略不计,清除/更新对用户来说是不可见的。